@Nullable
  public static PsiClass getSuperClass(@NotNull PsiClass psiClass) {
    PsiManager manager = psiClass.getManager();
    GlobalSearchScope resolveScope = psiClass.getResolveScope();

    final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
    if (psiClass.isInterface()) {
      return facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);
    }
    if (psiClass.isEnum()) {
      return facade.findClass(CommonClassNames.JAVA_LANG_ENUM, resolveScope);
    }

    if (psiClass instanceof PsiAnonymousClass) {
      PsiClassType baseClassReference = ((PsiAnonymousClass) psiClass).getBaseClassType();
      PsiClass baseClass = baseClassReference.resolve();
      if (baseClass == null || baseClass.isInterface())
        return facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);
      return baseClass;
    }

    if (CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) return null;

    final PsiClassType[] referenceElements = psiClass.getExtendsListTypes();

    if (referenceElements.length == 0)
      return facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);

    PsiClass psiResoved = referenceElements[0].resolve();
    return psiResoved == null
        ? facade.findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope)
        : psiResoved;
  }
Exemple #2
0
 public static boolean isAssignableFrom(
     final String baseQualifiedName, ReferenceType checkedType) {
   if (CommonClassNames.JAVA_LANG_OBJECT.equals(baseQualifiedName)) {
     return true;
   }
   return getSuperClass(baseQualifiedName, checkedType) != null;
 }
  /**
   * Creates a new {@link ClassElement} object.
   *
   * @param clazz class information.
   * @return a new {@link ClassElement} object.
   */
  public static ClassElement newClassElement(PsiClass clazz) {
    ClassElement ce = new ClassElement();

    // name
    ce.setName(clazz.getName());
    ce.setQualifiedName(clazz.getQualifiedName());

    // super
    PsiClass superClass = clazz.getSuperClass();
    if (superClass != null
        && !CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
      ce.setSuperName(superClass.getName());
    }

    // interfaces
    ce.setImplementNames(PsiAdapter.getImplementsClassnames(clazz));

    // other
    ce.setEnum(clazz.isEnum());
    ce.setDeprecated(clazz.isDeprecated());
    ce.setException(PsiAdapter.isExceptionClass(clazz));
    ce.setAbstract(clazz.hasModifierProperty(PsiModifier.ABSTRACT));
    ce.setTypeParams(clazz.getTypeParameters().length);

    return ce;
  }
Exemple #4
0
 @NotNull
 public static PsiElement[] findSuperElements(@NotNull PsiElement element) {
   if (element instanceof PsiClass) {
     PsiClass aClass = (PsiClass) element;
     List<PsiClass> allSupers = new ArrayList<>(Arrays.asList(aClass.getSupers()));
     for (Iterator<PsiClass> iterator = allSupers.iterator(); iterator.hasNext(); ) {
       PsiClass superClass = iterator.next();
       if (CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName()))
         iterator.remove();
     }
     return allSupers.toArray(new PsiClass[allSupers.size()]);
   }
   if (element instanceof PsiMethod) {
     PsiMethod method = (PsiMethod) element;
     if (method.isConstructor()) {
       PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method);
       if (constructorInSuper != null) {
         return new PsiMethod[] {constructorInSuper};
       }
     } else {
       PsiMethod[] superMethods = method.findSuperMethods(false);
       if (superMethods.length == 0) {
         PsiMethod superMethod = getSiblingInheritedViaSubClass(method);
         if (superMethod != null) {
           superMethods = new PsiMethod[] {superMethod};
         }
       }
       return superMethods;
     }
   }
   return PsiElement.EMPTY_ARRAY;
 }
  private int substituteToTypeParameters(
      PsiTypeElement typeElement,
      PsiTypeElement inplaceTypeElement,
      PsiType[] paramVals,
      PsiTypeParameter[] params,
      TemplateBuilder builder,
      PsiSubstitutor rawingSubstitutor,
      boolean toplevel) {
    PsiType type = inplaceTypeElement.getType();
    List<PsiType> types = new ArrayList<>();
    for (int i = 0; i < paramVals.length; i++) {
      PsiType val = paramVals[i];
      if (val == null) return SUBSTITUTED_NONE;
      if (type.equals(val)) {
        types.add(myFactory.createType(params[i]));
      }
    }

    if (!types.isEmpty()) {
      Project project = typeElement.getProject();
      PsiType substituted = rawingSubstitutor.substitute(type);
      if (!CommonClassNames.JAVA_LANG_OBJECT.equals(substituted.getCanonicalText())
          && (toplevel || substituted.equals(type))) {
        types.add(substituted);
      }

      builder.replaceElement(
          typeElement,
          new TypeExpression(project, types.toArray(PsiType.createArray(types.size()))));
      return toplevel ? SUBSTITUTED_IN_REF : SUBSTITUTED_IN_PARAMETERS;
    }

    boolean substituted = false;
    PsiJavaCodeReferenceElement ref = typeElement.getInnermostComponentReferenceElement();
    PsiJavaCodeReferenceElement inplaceRef =
        inplaceTypeElement.getInnermostComponentReferenceElement();
    if (ref != null) {
      LOG.assertTrue(inplaceRef != null);
      PsiTypeElement[] innerTypeElements = ref.getParameterList().getTypeParameterElements();
      PsiTypeElement[] inplaceInnerTypeElements =
          inplaceRef.getParameterList().getTypeParameterElements();
      for (int i = 0; i < innerTypeElements.length; i++) {
        substituted |=
            substituteToTypeParameters(
                    innerTypeElements[i],
                    inplaceInnerTypeElements[i],
                    paramVals,
                    params,
                    builder,
                    rawingSubstitutor,
                    false)
                != SUBSTITUTED_NONE;
      }
    }

    return substituted ? SUBSTITUTED_IN_PARAMETERS : SUBSTITUTED_NONE;
  }
Exemple #6
0
 private static boolean canHaveSiblingSuper(PsiMethod method, PsiClass containingClass) {
   return containingClass != null
       && PsiUtil.canBeOverriden(method)
       && !method.hasModifierProperty(PsiModifier.ABSTRACT)
       && !method.hasModifierProperty(PsiModifier.NATIVE)
       && method.hasModifierProperty(PsiModifier.PUBLIC)
       && !containingClass.isInterface()
       && !CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName());
 }
 private static boolean canHaveSuperMethod(
     PsiMethod method, boolean checkAccess, boolean allowStaticMethod) {
   if (method.isConstructor()) return false;
   if (!allowStaticMethod && method.hasModifierProperty(PsiModifier.STATIC)) return false;
   if (checkAccess && method.hasModifierProperty(PsiModifier.PRIVATE)) return false;
   PsiClass parentClass = method.getContainingClass();
   return parentClass != null
       && !CommonClassNames.JAVA_LANG_OBJECT.equals(parentClass.getQualifiedName());
 }
  private static boolean overridesObjectOrGroovyObject(PsiMethod method) {
    final String name = method.getName();
    if (!OBJECT_METHODS.contains(name) && !GROOVY_OBJECT_METHODS.contains(name)) return false;

    final PsiMethod superMethod = PsiSuperMethodImplUtil.findDeepestSuperMethod(method);
    if (superMethod == null) return false;

    final PsiClass superClass = superMethod.getContainingClass();
    if (superClass == null) return false;

    final String qname = superClass.getQualifiedName();
    return CommonClassNames.JAVA_LANG_OBJECT.equals(qname)
        || GroovyCommonClassNames.GROOVY_OBJECT.equals(qname);
  }
  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);
  }
 private boolean hasGoodToString(PsiClass aClass) {
   final PsiMethod[] methods =
       aClass.findMethodsByName(HardcodedMethodConstants.TO_STRING, true);
   for (PsiMethod method : methods) {
     final PsiClass containingClass = method.getContainingClass();
     if (containingClass == null) {
       continue;
     }
     final String name = containingClass.getQualifiedName();
     if (CommonClassNames.JAVA_LANG_OBJECT.equals(name)) {
       continue;
     }
     final PsiParameterList parameterList = method.getParameterList();
     if (parameterList.getParametersCount() == 0) {
       return true;
     }
   }
   return false;
 }
  private static boolean isSuperMethod(
      PsiClass aClass,
      HierarchicalMethodSignature hierarchicalMethodSignature,
      HierarchicalMethodSignature superSignatureHierarchical) {
    PsiMethod superMethod = superSignatureHierarchical.getMethod();
    PsiClass superClass = superMethod.getContainingClass();
    PsiClass containingClass = hierarchicalMethodSignature.getMethod().getContainingClass();
    if (!superMethod.isConstructor()) {
      if (!aClass.equals(superClass)) {
        if (PsiUtil.isAccessible(aClass.getProject(), superMethod, aClass, aClass)) {
          if (MethodSignatureUtil.isSubsignature(
              superSignatureHierarchical, hierarchicalMethodSignature)) {
            if (superClass != null) {
              if (superClass.isInterface()
                  || CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
                if (superMethod.hasModifierProperty(PsiModifier.DEFAULT)
                    || hierarchicalMethodSignature
                        .getMethod()
                        .hasModifierProperty(PsiModifier.DEFAULT)) {
                  return !InheritanceUtil.isInheritorOrSelf(superClass, containingClass, true);
                }
                return true;
              }

              if (containingClass != null) {
                if (containingClass.isInterface()) {
                  return false;
                }

                if (!aClass.isInterface()
                    && !InheritanceUtil.isInheritorOrSelf(superClass, containingClass, true)) {
                  return true;
                }
              }
            }
          }
        }
      }
    }
    return false;
  }
 @NotNull
 @Override
 public PsiClassType createTypeByFQClassName(
     @NotNull final String qName, @NotNull final GlobalSearchScope resolveScope) {
   if (CommonClassNames.JAVA_LANG_OBJECT.equals(qName)) {
     PsiClassType cachedObjectType = myCachedObjectType.get(resolveScope);
     if (cachedObjectType != null) {
       return cachedObjectType;
     }
     PsiClass aClass =
         JavaPsiFacade.getInstance(myManager.getProject())
             .findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);
     if (aClass != null) {
       cachedObjectType = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY);
       cachedObjectType = myCachedObjectType.cacheOrGet(resolveScope, cachedObjectType);
       return cachedObjectType;
     }
   }
   return new PsiClassReferenceType(
       createReferenceElementByFQClassName(qName, resolveScope), null);
 }
  @Nullable
  private PsiType getSuperType(PsiClass aClass) {
    if (aClass.isInterface()) {
      return PsiType.getJavaLangObject(getManager(), getResolveScope());
    }
    if (aClass instanceof GrAnonymousClassDefinition) {
      final PsiClassType baseClassType = ((GrAnonymousClassDefinition) aClass).getBaseClassType();
      final PsiClass psiClass = baseClassType.resolve();
      if (psiClass != null && !psiClass.isInterface()) {
        return baseClassType;
      }

      return PsiType.getJavaLangObject(getManager(), getResolveScope());
    }

    if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return null;
    PsiClassType[] superTypes = aClass.getExtendsListTypes();
    if (superTypes.length == 0) {
      return PsiType.getJavaLangObject(getManager(), getResolveScope());
    }

    return superTypes[0];
  }
 public static HighlightInfo checkClashesWithSuperMethods(@NotNull PsiAnnotationMethod psiMethod) {
   final PsiIdentifier nameIdentifier = psiMethod.getNameIdentifier();
   if (nameIdentifier != null) {
     final PsiMethod[] methods = psiMethod.findDeepestSuperMethods();
     for (PsiMethod method : methods) {
       final PsiClass containingClass = method.getContainingClass();
       if (containingClass != null) {
         final String qualifiedName = containingClass.getQualifiedName();
         if (CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)
             || CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION.equals(qualifiedName)) {
           return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
               .range(nameIdentifier)
               .descriptionAndTooltip(
                   "@interface member clashes with '"
                       + JavaHighlightUtil.formatMethod(method)
                       + "' in "
                       + HighlightUtil.formatClass(containingClass))
               .create();
         }
       }
     }
   }
   return null;
 }
  private static void addInheritorClassLiterals(
      final PsiFile context,
      Condition<String> shortNameCondition,
      final PsiType classParameter,
      final Consumer<LookupElement> result,
      PrefixMatcher matcher) {
    final String canonicalText = classParameter.getCanonicalText();
    if (CommonClassNames.JAVA_LANG_OBJECT.equals(canonicalText)
        && StringUtil.isEmpty(matcher.getPrefix())) {
      return;
    }

    CodeInsightUtil.processSubTypes(
        classParameter,
        context,
        true,
        shortNameCondition,
        new Consumer<PsiType>() {
          @Override
          public void consume(PsiType type) {
            addClassLiteralLookupElement(type, result, context);
          }
        });
  }
  @NotNull
  public static PsiClassType[] getSuperTypes(@NotNull PsiClass psiClass) {
    if (psiClass instanceof PsiAnonymousClass) {
      PsiClassType baseClassType = ((PsiAnonymousClass) psiClass).getBaseClassType();
      PsiClass baseClass = baseClassType.resolve();
      if (baseClass == null || !baseClass.isInterface()) {
        return new PsiClassType[] {baseClassType};
      } else {
        PsiClassType objectType =
            PsiType.getJavaLangObject(psiClass.getManager(), psiClass.getResolveScope());
        return new PsiClassType[] {objectType, baseClassType};
      }
    }

    PsiClassType[] extendsTypes = psiClass.getExtendsListTypes();
    PsiClassType[] implementsTypes = psiClass.getImplementsListTypes();
    boolean hasExtends = extendsTypes.length != 0;
    int extendsListLength = extendsTypes.length + (hasExtends ? 0 : 1);
    PsiClassType[] result = new PsiClassType[extendsListLength + implementsTypes.length];

    System.arraycopy(extendsTypes, 0, result, 0, extendsTypes.length);
    if (!hasExtends) {
      if (CommonClassNames.JAVA_LANG_OBJECT.equals(psiClass.getQualifiedName())) {
        return PsiClassType.EMPTY_ARRAY;
      }
      PsiManager manager = psiClass.getManager();
      PsiClassType objectType = PsiType.getJavaLangObject(manager, psiClass.getResolveScope());
      result[0] = objectType;
    }
    System.arraycopy(implementsTypes, 0, result, extendsListLength, implementsTypes.length);
    for (int i = 0; i < result.length; i++) {
      PsiClassType type = result[i];
      result[i] = (PsiClassType) PsiUtil.captureToplevelWildcards(type, psiClass);
    }
    return result;
  }
  @Nullable
  private PsiType getNominalTypeInner(PsiElement resolved) {
    if (resolved == null && !"class".equals(getReferenceName())) {
      resolved = resolve();
    }

    if (resolved instanceof PsiClass) {
      final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
      if (PsiUtil.isInstanceThisRef(this)) {
        final PsiClassType categoryType = GdkMethodUtil.getCategoryType((PsiClass) resolved);
        if (categoryType != null) {
          return categoryType;
        } else {
          return factory.createType((PsiClass) resolved);
        }
      }
      if (getParent() instanceof GrReferenceExpression || PsiUtil.isSuperReference(this)) {
        return factory.createType((PsiClass) resolved);
      } else {
        return TypesUtil.createJavaLangClassType(
            factory.createType((PsiClass) resolved), getProject(), getResolveScope());
      }
    }

    if (resolved instanceof GrVariable) {
      return ((GrVariable) resolved).getDeclaredType();
    }

    if (resolved instanceof PsiVariable) {
      return ((PsiVariable) resolved).getType();
    }

    if (resolved instanceof PsiMethod) {
      PsiMethod method = (PsiMethod) resolved;
      if (PropertyUtil.isSimplePropertySetter(method)
          && !method.getName().equals(getReferenceName())) {
        return method.getParameterList().getParameters()[0].getType();
      }

      // 'class' property with explicit generic
      PsiClass containingClass = method.getContainingClass();
      if (containingClass != null
          && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())
          && "getClass".equals(method.getName())) {
        return TypesUtil.createJavaLangClassType(
            GrReferenceResolveUtil.getQualifierType(this), getProject(), getResolveScope());
      }

      return PsiUtil.getSmartReturnType(method);
    }

    if (resolved instanceof GrReferenceExpression) {
      PsiElement parent = resolved.getParent();
      if (parent instanceof GrAssignmentExpression) {
        GrAssignmentExpression assignment = (GrAssignmentExpression) parent;
        if (resolved.equals(assignment.getLValue())) {
          GrExpression rValue = assignment.getRValue();
          if (rValue != null) {
            PsiType rType = rValue.getType();
            if (rType != null) {
              return rType;
            }
          }
        }
      }
    }

    if (resolved == null) {
      final PsiType fromClassRef = getTypeFromClassRef(this);
      if (fromClassRef != null) {
        return fromClassRef;
      }

      final PsiType fromMapAccess = getTypeFromMapAccess(this);
      if (fromMapAccess != null) {
        return fromMapAccess;
      }

      final PsiType fromSpreadOperator = getTypeFromSpreadOperator(this);
      if (fromSpreadOperator != null) {
        return fromSpreadOperator;
      }
    }

    return null;
  }
  @SuppressWarnings({"HardCodedStringLiteral"})
  private static String generateClassInfo(PsiClass aClass) {
    StringBuilder buffer = new StringBuilder();
    GroovyFile file = (GroovyFile) aClass.getContainingFile();

    String packageName = file.getPackageName();
    if (packageName.length() > 0) {
      buffer.append(packageName).append("\n");
    }

    final String classString =
        aClass.isInterface()
            ? "interface"
            : aClass instanceof PsiTypeParameter
                ? "type parameter"
                : aClass.isEnum() ? "enum" : "class";
    buffer.append(classString).append(" ").append(aClass.getName());

    if (aClass.hasTypeParameters()) {
      PsiTypeParameter[] typeParameters = aClass.getTypeParameters();

      buffer.append("<");

      for (int i = 0; i < typeParameters.length; i++) {
        if (i > 0) buffer.append(", ");

        PsiTypeParameter tp = typeParameters[i];

        buffer.append(tp.getName());

        PsiClassType[] refs = tp.getExtendsListTypes();

        if (refs.length > 0) {
          buffer.append(" extends ");

          for (int j = 0; j < refs.length; j++) {
            if (j > 0) buffer.append(" & ");
            appendTypeString(buffer, refs[j], aClass);
          }
        }
      }

      buffer.append(">");
    }

    PsiClassType[] refs = aClass.getExtendsListTypes();
    if (refs.length > 0
        || !aClass.isInterface()
            && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) {
      buffer.append(" extends ");
      if (refs.length == 0) {
        buffer.append("Object");
      } else {
        for (int i = 0; i < refs.length; i++) {
          if (i > 0) buffer.append(", ");
          appendTypeString(buffer, refs[i], aClass);
        }
      }
    }

    refs = aClass.getImplementsListTypes();
    if (refs.length > 0) {
      buffer.append("\nimplements ");
      for (int i = 0; i < refs.length; i++) {
        if (i > 0) buffer.append(", ");
        appendTypeString(buffer, refs[i], aClass);
      }
    }

    return buffer.toString();
  }
  protected void checkSameSignatures(@NotNull List<CandidateInfo> conflicts) {
    // candidates should go in order of class hierarchy traversal
    // in order for this to work
    Map<MethodSignature, CandidateInfo> signatures =
        new THashMap<MethodSignature, CandidateInfo>(conflicts.size());
    Set<PsiMethod> superMethods = new HashSet<PsiMethod>();
    for (CandidateInfo conflict : conflicts) {
      final PsiMethod method = ((MethodCandidateInfo) conflict).getElement();
      for (HierarchicalMethodSignature methodSignature :
          method.getHierarchicalMethodSignature().getSuperSignatures()) {
        final PsiMethod superMethod = methodSignature.getMethod();
        final PsiClass aClass = superMethod.getContainingClass();
        if (aClass != null
            && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) {
          superMethods.add(superMethod);
        }
      }
    }
    nextConflict:
    for (int i = 0; i < conflicts.size(); i++) {
      ProgressManager.checkCanceled();
      CandidateInfo info = conflicts.get(i);
      PsiMethod method = (PsiMethod) info.getElement();

      if (!method.hasModifierProperty(PsiModifier.STATIC) && superMethods.contains(method)) {
        conflicts.remove(i);
        i--;
        continue;
      }

      PsiClass class1 = method.getContainingClass();
      PsiSubstitutor infoSubstitutor = ((MethodCandidateInfo) info).getSubstitutor(false);
      MethodSignature signature = method.getSignature(infoSubstitutor);
      CandidateInfo existing = signatures.get(signature);

      if (existing == null) {
        signatures.put(signature, info);
        continue;
      }
      PsiMethod existingMethod = (PsiMethod) existing.getElement();
      PsiClass existingClass = existingMethod.getContainingClass();
      if (class1 != null
          && existingClass != null) { // prefer interface methods to methods from Object
        if (class1.isInterface()
            && CommonClassNames.JAVA_LANG_OBJECT.equals(existingClass.getQualifiedName())) {
          signatures.put(signature, info);
          continue;
        } else if (existingClass.isInterface()
            && CommonClassNames.JAVA_LANG_OBJECT.equals(class1.getQualifiedName())) {
          conflicts.remove(info);
          i--;
          continue;
        }
      }
      if (method == existingMethod) {
        PsiElement scope1 = info.getCurrentFileResolveScope();
        PsiElement scope2 = existing.getCurrentFileResolveScope();
        if (scope1 instanceof PsiClass
            && scope2 instanceof PsiClass
            && PsiTreeUtil.isAncestor(scope1, scope2, true)
            && !existing
                .isAccessible()) { // prefer methods from outer class to inaccessible base class
                                   // methods
          signatures.put(signature, info);
          continue;
        }
      }

      // filter out methods with incorrect inferred bounds (for unrelated methods only)
      boolean existingTypeParamAgree = areTypeParametersAgree(existing);
      boolean infoTypeParamAgree = areTypeParametersAgree(info);
      if (existingTypeParamAgree
          && !infoTypeParamAgree
          && !PsiSuperMethodImplUtil.isSuperMethodSmart(method, existingMethod)) {
        conflicts.remove(i);
        i--;
        continue;
      }
      if (!existingTypeParamAgree
          && infoTypeParamAgree
          && !PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) {
        signatures.put(signature, info);
        int index = conflicts.indexOf(existing);
        conflicts.remove(index);
        i--;
        continue;
      }

      if (InheritanceUtil.isInheritorOrSelf(class1, existingClass, true)
          || InheritanceUtil.isInheritorOrSelf(existingClass, class1, true)) {
        PsiParameter[] parameters = method.getParameterList().getParameters();
        final PsiParameter[] existingParameters = existingMethod.getParameterList().getParameters();
        for (int i1 = 0, parametersLength = parameters.length; i1 < parametersLength; i1++) {
          if (parameters[i1].getType() instanceof PsiArrayType
              && !(existingParameters[i1].getType()
                  instanceof PsiArrayType)) { // prefer more specific type
            signatures.put(signature, info);
            continue nextConflict;
          }
        }
        PsiType returnType1 = method.getReturnType();
        PsiType returnType2 = existingMethod.getReturnType();
        if (returnType1 != null && returnType2 != null) {
          returnType1 = infoSubstitutor.substitute(returnType1);
          returnType2 =
              ((MethodCandidateInfo) existing).getSubstitutor(false).substitute(returnType2);
          if (!returnType1.equals(returnType2) && returnType1.isAssignableFrom(returnType2)) {
            conflicts.remove(i);
            i--;
            continue;
          }
        }

        // prefer derived class
        signatures.put(signature, info);
      } else {
        final PsiMethodCallExpression methodCallExpression =
            PsiTreeUtil.getParentOfType(myArgumentsList, PsiMethodCallExpression.class);
        if (methodCallExpression != null) {
          final PsiReferenceExpression expression = methodCallExpression.getMethodExpression();
          final PsiExpression qualifierExpression = expression.getQualifierExpression();
          PsiClass currentClass;
          if (qualifierExpression != null) {
            currentClass = PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType());
          } else {
            currentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
          }

          if (currentClass != null && existingClass != null && class1 != null) {
            final PsiSubstitutor eSubstitutor =
                TypeConversionUtil.getMaybeSuperClassSubstitutor(
                    existingClass, currentClass, PsiSubstitutor.EMPTY, null);
            final PsiSubstitutor cSubstitutor =
                TypeConversionUtil.getMaybeSuperClassSubstitutor(
                    class1, currentClass, PsiSubstitutor.EMPTY, null);
            if (eSubstitutor != null
                && cSubstitutor != null
                && MethodSignatureUtil.areSignaturesEqual(
                    existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) {
              final PsiType returnType = eSubstitutor.substitute(existingMethod.getReturnType());
              final PsiType returnType1 = cSubstitutor.substitute(method.getReturnType());
              if (returnType != null && returnType1 != null && !returnType1.equals(returnType)) {
                if (TypeConversionUtil.isAssignable(returnType, returnType1, false)) {
                  if (class1.isInterface() && !existingClass.isInterface()) continue;
                  conflicts.remove(existing);
                } else {
                  if (!TypeConversionUtil.isAssignable(returnType1, returnType, false)) continue;
                  conflicts.remove(i);
                }
                i--;
                break;
              }
            }
          }
        }
      }
    }
  }
  @Nullable
  private PsiType getNominalTypeInner(@Nullable PsiElement resolved) {
    if (resolved == null && !"class".equals(getReferenceName())) {
      resolved = resolve();
    }

    if (resolved instanceof PsiClass) {
      final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
      if (PsiUtil.isInstanceThisRef(this)) {
        final PsiClassType categoryType = GdkMethodUtil.getCategoryType((PsiClass) resolved);
        if (categoryType != null) {
          return categoryType;
        } else {
          return factory.createType((PsiClass) resolved);
        }
      } else if (PsiUtil.isSuperReference(this)) {
        PsiClass contextClass = PsiUtil.getContextClass(this);
        if (GrTraitUtil.isTrait(contextClass)) {
          PsiClassType[] extendsTypes = contextClass.getExtendsListTypes();
          PsiClassType[] implementsTypes = contextClass.getImplementsListTypes();

          PsiClassType[] superTypes =
              ArrayUtil.mergeArrays(implementsTypes, extendsTypes, PsiClassType.ARRAY_FACTORY);

          return PsiIntersectionType.createIntersection(ArrayUtil.reverseArray(superTypes));
        }
        return factory.createType((PsiClass) resolved);
      }
      if (getParent() instanceof GrReferenceExpression) {
        return factory.createType((PsiClass) resolved);
      } else {
        return TypesUtil.createJavaLangClassType(
            factory.createType((PsiClass) resolved), getProject(), getResolveScope());
      }
    }

    if (resolved instanceof GrVariable) {
      return ((GrVariable) resolved).getDeclaredType();
    }

    if (resolved instanceof PsiVariable) {
      return ((PsiVariable) resolved).getType();
    }

    if (resolved instanceof PsiMethod) {
      PsiMethod method = (PsiMethod) resolved;
      if (PropertyUtil.isSimplePropertySetter(method)
          && !method.getName().equals(getReferenceName())) {
        return method.getParameterList().getParameters()[0].getType();
      }

      // 'class' property with explicit generic
      PsiClass containingClass = method.getContainingClass();
      if (containingClass != null
          && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())
          && "getClass".equals(method.getName())) {
        return TypesUtil.createJavaLangClassType(
            PsiImplUtil.getQualifierType(this), getProject(), getResolveScope());
      }

      return PsiUtil.getSmartReturnType(method);
    }

    if (resolved == null) {
      final PsiType fromClassRef = getTypeFromClassRef(this);
      if (fromClassRef != null) {
        return fromClassRef;
      }

      final PsiType fromMapAccess = getTypeFromMapAccess(this);
      if (fromMapAccess != null) {
        return fromMapAccess;
      }

      final PsiType fromSpreadOperator = getTypeFromSpreadOperator(this);
      if (fromSpreadOperator != null) {
        return fromSpreadOperator;
      }
    }

    return null;
  }