public void testRunningAllInPackage() throws IOException, ExecutionException {
   Module module1 = getModule1();
   GlobalSearchScope module1AndLibraries = GlobalSearchScope.moduleWithLibrariesScope(module1);
   PsiClass testCase = findClass(TestCase.class.getName(), module1AndLibraries);
   PsiClass psiClass = findTestA(module1);
   PsiClass psiClass2 = findTestA(getModule2());
   PsiClass derivedTest = findClass(module1, "test1.DerivedTest");
   PsiClass baseTestCase = findClass("junit.framework.ThirdPartyClass", module1AndLibraries);
   PsiClass testB = findClass(getModule3(), "test1.TestB");
   assertNotNull(testCase);
   assertNotNull(derivedTest);
   assertNotNull(psiClass);
   assertTrue(psiClass.isInheritor(testCase, false));
   assertEquals(baseTestCase, derivedTest.getSuperClass());
   assertTrue(baseTestCase.isInheritor(testCase, true));
   assertTrue(derivedTest.isInheritor(testCase, true));
   PsiPackage psiPackage = JUnitUtil.getContainingPackage(psiClass);
   JUnitConfiguration configuration = createConfiguration(psiPackage, module1);
   JavaParameters parameters = checkCanRun(configuration);
   List<String> lines = extractAllInPackageTests(parameters, psiPackage);
   Assertion.compareUnordered(
       new Object[] {
         "",
         psiClass.getQualifiedName(),
         psiClass2.getQualifiedName(),
         derivedTest.getQualifiedName(),
         RT_INNER_TEST_NAME,
         testB.getQualifiedName()
       },
       lines);
 }
 private void doMoveClass(PsiSubstitutor substitutor, MemberInfo info) {
   PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
   PsiClass aClass = (PsiClass) info.getMember();
   if (Boolean.FALSE.equals(info.getOverrides())) {
     final PsiReferenceList sourceReferenceList = info.getSourceReferenceList();
     LOG.assertTrue(sourceReferenceList != null);
     PsiJavaCodeReferenceElement ref =
         mySourceClass.equals(sourceReferenceList.getParent())
             ? RefactoringUtil.removeFromReferenceList(sourceReferenceList, aClass)
             : RefactoringUtil.findReferenceToClass(sourceReferenceList, aClass);
     if (ref != null && !myTargetSuperClass.isInheritor(aClass, false)) {
       RefactoringUtil.replaceMovedMemberTypeParameters(
           ref, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
       final PsiReferenceList referenceList =
           myIsTargetInterface
               ? myTargetSuperClass.getExtendsList()
               : myTargetSuperClass.getImplementsList();
       assert referenceList != null;
       referenceList.add(ref);
     }
   } else {
     RefactoringUtil.replaceMovedMemberTypeParameters(
         aClass, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory);
     fixReferencesToStatic(aClass);
     final PsiMember movedElement =
         (PsiMember)
             myTargetSuperClass.add(
                 convertClassToLanguage(aClass, myTargetSuperClass.getLanguage()));
     myMembersAfterMove.add(movedElement);
     aClass.delete();
   }
 }
 @Nullable
 private static PsiMethodCallExpression checkMethodResolvable(
     PsiMethodCallExpression methodCall,
     PsiMethod targetMethod,
     PsiReferenceExpression context,
     PsiClass aClass)
     throws IncorrectOperationException {
   PsiElementFactory factory =
       JavaPsiFacade.getInstance(targetMethod.getProject()).getElementFactory();
   final PsiElement resolved = methodCall.getMethodExpression().resolve();
   if (resolved != targetMethod) {
     PsiClass containingClass;
     if (resolved instanceof PsiMethod) {
       containingClass = ((PsiMethod) resolved).getContainingClass();
     } else if (resolved instanceof PsiClass) {
       containingClass = (PsiClass) resolved;
     } else {
       return null;
     }
     if (containingClass != null && containingClass.isInheritor(aClass, false)) {
       final PsiExpression newMethodExpression =
           factory.createExpressionFromText("super." + targetMethod.getName(), context);
       methodCall.getMethodExpression().replace(newMethodExpression);
     } else {
       methodCall = null;
     }
   }
   return methodCall;
 }
 public static boolean inheritsITestListener(@NotNull PsiClass psiClass) {
   final Project project = psiClass.getProject();
   final PsiClass aListenerClass =
       JavaPsiFacade.getInstance(project)
           .findClass(ITestNGListener.class.getName(), GlobalSearchScope.allScope(project));
   return aListenerClass != null && psiClass.isInheritor(aListenerClass, true);
 }
 public void testEnum() throws Exception {
   setupLoadingFilter();
   final PsiClass enumClass =
       myJavaFacade.findClass("enums.OurEnum", GlobalSearchScope.moduleScope(myModule));
   assertNotNull(enumClass);
   assertTrue(enumClass.isEnum());
   final PsiClass superClass = enumClass.getSuperClass();
   assertNotNull(superClass);
   assertEquals("java.lang.Enum", superClass.getQualifiedName());
   assertTrue(enumClass.isInheritor(superClass, false));
   final PsiClassType[] superTypes = enumClass.getSuperTypes();
   assertEquals(1, superTypes.length);
   assertEquals("java.lang.Enum<enums.OurEnum>", superTypes[0].getCanonicalText());
   final PsiClass[] supers = enumClass.getSupers();
   assertEquals(1, supers.length);
   assertEquals("java.lang.Enum", supers[0].getQualifiedName());
   final PsiClassType[] extendsListTypes = enumClass.getExtendsListTypes();
   assertEquals(1, extendsListTypes.length);
   assertEquals("java.lang.Enum<enums.OurEnum>", extendsListTypes[0].getCanonicalText());
   final PsiSubstitutor superClassSubstitutor =
       TypeConversionUtil.getSuperClassSubstitutor(superClass, enumClass, PsiSubstitutor.EMPTY);
   assertEquals(
       "java.lang.Enum<enums.OurEnum>",
       myJavaFacade
           .getElementFactory()
           .createType(superClass, superClassSubstitutor)
           .getCanonicalText());
   teardownLoadingFilter();
 }
    private void checkSimpleClasses(PsiType ltype, PsiType rtype, GrBinaryExpression expression) {
      if (!(rtype instanceof PsiClassType)) return;
      if (!(ltype instanceof PsiClassType)) return;

      PsiClass lclass = ((PsiClassType) ltype).resolve();
      PsiClass rclass = ((PsiClassType) rtype).resolve();

      if (lclass == null || rclass == null) return;

      if (expression.getManager().areElementsEquivalent(lclass, rclass)) return;

      if (lclass.isInterface() || rclass.isInterface()) return;

      if (lclass.isInheritor(rclass, true) || rclass.isInheritor(lclass, true)) return;

      registerError(expression, ltype, rtype);
    }
  private static void addSuper(final Set<PsiClass> supers, final PsiClass classToAdd) {
    for (Iterator<PsiClass> iterator = supers.iterator(); iterator.hasNext(); ) {
      PsiClass superClass = iterator.next();
      if (InheritanceUtil.isInheritorOrSelf(superClass, classToAdd, true)) return;
      if (classToAdd.isInheritor(superClass, true)) iterator.remove();
    }

    supers.add(classToAdd);
  }
 private boolean isAmbiguousInherited(PsiClass containingClass1) {
   PsiClass psiClass = PsiTreeUtil.getParentOfType(myPlace, PsiClass.class);
   while (psiClass != null) {
     if (psiClass.isInheritor(containingClass1, false)) {
       return true;
     }
     psiClass = psiClass.getContainingClass();
   }
   return false;
 }
 public String getConflictingConjunctsMessage() {
   final PsiType[] conjuncts = getConjuncts();
   for (int i = 0; i < conjuncts.length; i++) {
     PsiClass conjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i]);
     if (conjunct != null && !conjunct.isInterface()) {
       for (int i1 = i + 1; i1 < conjuncts.length; i1++) {
         PsiClass oppositeConjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i1]);
         if (oppositeConjunct != null && !oppositeConjunct.isInterface()) {
           if (!conjunct.isInheritor(oppositeConjunct, true)
               && !oppositeConjunct.isInheritor(conjunct, true)) {
             return conjuncts[i].getPresentableText()
                 + " and "
                 + conjuncts[i1].getPresentableText();
           }
         }
       }
     }
   }
   return null;
 }
  @Nullable
  private ProblemDescriptor createDescription(
      @NotNull PsiTypeCastExpression cast, @NotNull InspectionManager manager, boolean onTheFly) {
    PsiExpression operand = cast.getOperand();
    PsiTypeElement castType = cast.getCastType();
    if (operand == null || castType == null) return null;
    PsiElement parent = cast.getParent();
    while (parent instanceof PsiParenthesizedExpression) {
      parent = parent.getParent();
    }
    if (parent instanceof PsiReferenceExpression) {
      if (IGNORE_ANNOTATED_METHODS) {
        final PsiElement gParent = parent.getParent();
        if (gParent instanceof PsiMethodCallExpression) {
          final PsiMethod psiMethod = ((PsiMethodCallExpression) gParent).resolveMethod();
          if (psiMethod != null && NullableNotNullManager.isNotNull(psiMethod)) {
            final PsiClass superClass = PsiUtil.resolveClassInType(operand.getType());
            final PsiClass containingClass = psiMethod.getContainingClass();
            if (containingClass != null
                && superClass != null
                && containingClass.isInheritor(superClass, true)) {
              for (PsiMethod method : psiMethod.findSuperMethods(superClass)) {
                if (NullableNotNullManager.isNullable(method)) {
                  return null;
                }
              }
            }
          }
        }
      }
    } else if (parent instanceof PsiExpressionList) {
      final PsiElement gParent = parent.getParent();
      if (gParent instanceof PsiMethodCallExpression && IGNORE_SUSPICIOUS_METHOD_CALLS) {
        final String message =
            SuspiciousCollectionsMethodCallsInspection.getSuspiciousMethodCallMessage(
                (PsiMethodCallExpression) gParent,
                operand.getType(),
                true,
                new ArrayList<PsiMethod>(),
                new IntArrayList());
        if (message != null) {
          return null;
        }
      }
    }

    String message =
        InspectionsBundle.message(
            "inspection.redundant.cast.problem.descriptor",
            "<code>" + operand.getText() + "</code>",
            "<code>#ref</code> #loc");
    return manager.createProblemDescriptor(
        castType, message, myQuickFixAction, ProblemHighlightType.LIKE_UNUSED_SYMBOL, onTheFly);
  }
  @Override
  public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) {
    for (PsiType type : getBounds(InferenceBound.UPPER)) {
      PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(type);
      if (psiClass != null) {
        if (getManager().areElementsEquivalent(baseClass, psiClass)) return true;
        if (checkDeep && psiClass.isInheritor(baseClass, true)) return true;
      }
    }

    return super.isInheritor(baseClass, checkDeep);
  }
 /**
  * Returns true if the given associated activity class is either found in the given set of
  * classes, or (less likely) extends any of the classes in that set
  */
 private static boolean containsOrExtends(
     @NotNull Set<PsiClass> resolvedClasses, @NotNull PsiClass relatedActivity) {
   if (resolvedClasses.contains(relatedActivity)) {
     return true;
   }
   for (PsiClass resolvedClass : resolvedClasses) {
     if (relatedActivity.isInheritor(resolvedClass, false)) {
       return true;
     }
   }
   return false;
 }
 private static void getLeastUpperClassesInner(
     PsiClass aClass, PsiClass bClass, Set<PsiClass> supers, Set<PsiClass> visited) {
   if (bClass.isInheritor(aClass, true)) {
     addSuper(supers, aClass);
   } else {
     final PsiClass[] aSupers = aClass.getSupers();
     for (PsiClass aSuper : aSupers) {
       if (visited.add(aSuper)) {
         getLeastUpperClassesInner(aSuper, bClass, supers, visited);
       }
     }
   }
 }
 public static boolean isSuperMethod(
     @NotNull PsiMethod superMethodCandidate, @NotNull PsiMethod derivedMethod) {
   PsiClass superClassCandidate = superMethodCandidate.getContainingClass();
   PsiClass derivedClass = derivedMethod.getContainingClass();
   if (derivedClass == null || superClassCandidate == null) return false;
   if (!derivedClass.isInheritor(superClassCandidate, true)) return false;
   final PsiSubstitutor superSubstitutor =
       TypeConversionUtil.getSuperClassSubstitutor(
           superClassCandidate, derivedClass, PsiSubstitutor.EMPTY);
   final MethodSignature superSignature = superMethodCandidate.getSignature(superSubstitutor);
   final MethodSignature derivedSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY);
   return isSubsignature(superSignature, derivedSignature);
 }
  @Override
  public ProblemDescriptor[] checkClass(
      @NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
    final Project project = aClass.getProject();
    final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
    final Module module = ModuleUtil.findModuleForPsiElement(aClass);

    if (nameIdentifier == null || module == null || !PsiUtil.isInstanciatable(aClass)) return null;

    final PsiClass base =
        JavaPsiFacade.getInstance(project)
            .findClass(INTENTION, GlobalSearchScope.allScope(project));

    if (base == null || !aClass.isInheritor(base, true)) return null;

    String descriptionDir = getDescriptionDirName(aClass);
    if (StringUtil.isEmptyOrSpaces(descriptionDir)) {
      return null;
    }

    for (PsiDirectory description : getIntentionDescriptionsDirs(module)) {
      PsiDirectory dir = description.findSubdirectory(descriptionDir);
      if (dir == null) continue;
      final PsiFile descr = dir.findFile("description.html");
      if (descr != null) {
        if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) {
          PsiElement problem = aClass.getNameIdentifier();
          ProblemDescriptor problemDescriptor =
              manager.createProblemDescriptor(
                  problem == null ? nameIdentifier : problem,
                  "Intention must have 'before.*.template' and 'after.*.template' beside 'description.html'",
                  isOnTheFly,
                  ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
          return new ProblemDescriptor[] {problemDescriptor};
        }

        return null;
      }
    }

    final PsiElement problem = aClass.getNameIdentifier();
    final ProblemDescriptor problemDescriptor =
        manager.createProblemDescriptor(
            problem == null ? nameIdentifier : problem,
            "Intention does not have a description",
            isOnTheFly,
            new LocalQuickFix[] {new CreateHtmlDescriptionFix(descriptionDir, module, true)},
            ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
    return new ProblemDescriptor[] {problemDescriptor};
  }
  private Domination dominates(
      PsiClass aClass, boolean accessible, String fqName, ClassCandidateInfo info) {
    final PsiClass otherClass = info.getElement();
    assert otherClass != null;
    String otherQName = otherClass.getQualifiedName();
    if (fqName.equals(otherQName)) {
      return Domination.DOMINATED_BY;
    }

    final PsiClass containingClass1 = aClass.getContainingClass();
    final PsiClass containingClass2 = otherClass.getContainingClass();
    if (containingClass1 != null
        && containingClass2 != null
        && containingClass2.isInheritor(containingClass1, true)
        && !isImported(myCurrentFileContext)) {
      // shadowing
      return Domination.DOMINATED_BY;
    }

    boolean infoAccessible = info.isAccessible();
    if (infoAccessible && !accessible) {
      return Domination.DOMINATED_BY;
    }
    if (!infoAccessible && accessible) {
      return Domination.DOMINATES;
    }

    // everything wins over class from default package
    boolean isDefault = StringUtil.getPackageName(fqName).length() == 0;
    boolean otherDefault =
        otherQName != null && StringUtil.getPackageName(otherQName).length() == 0;
    if (isDefault && !otherDefault) {
      return Domination.DOMINATED_BY;
    }
    if (!isDefault && otherDefault) {
      return Domination.DOMINATES;
    }

    // single import wins over on-demand
    boolean myOnDemand = isOnDemand(myCurrentFileContext, aClass);
    boolean otherOnDemand = isOnDemand(info.getCurrentFileResolveScope(), otherClass);
    if (myOnDemand && !otherOnDemand) {
      return Domination.DOMINATED_BY;
    }
    if (!myOnDemand && otherOnDemand) {
      return Domination.DOMINATES;
    }

    return Domination.EQUAL;
  }
  @Override
  public ProblemDescriptor[] checkClass(
      @NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
    final Project project = aClass.getProject();
    final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
    final Module module = ModuleUtilCore.findModuleForPsiElement(aClass);

    if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null;

    final PsiClass base =
        JavaPsiFacade.getInstance(project).findClass(getClassName(), aClass.getResolveScope());
    if (base == null || !aClass.isInheritor(base, true)) return null;

    String descriptionDir = DescriptionCheckerUtil.getDescriptionDirName(aClass);
    if (StringUtil.isEmptyOrSpaces(descriptionDir)) {
      return null;
    }

    for (PsiDirectory description : getDescriptionsDirs(module)) {
      PsiDirectory dir = description.findSubdirectory(descriptionDir);
      if (dir == null) continue;
      final PsiFile descr = dir.findFile("description.html");
      if (descr != null) {
        if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) {
          PsiElement problem = aClass.getNameIdentifier();
          ProblemDescriptor problemDescriptor =
              manager.createProblemDescriptor(
                  problem == null ? nameIdentifier : problem,
                  getHasNotBeforeAfterError(),
                  isOnTheFly,
                  ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
                  false);
          return new ProblemDescriptor[] {problemDescriptor};
        }

        return null;
      }
    }

    final PsiElement problem = aClass.getNameIdentifier();
    final ProblemDescriptor problemDescriptor =
        manager.createProblemDescriptor(
            problem == null ? nameIdentifier : problem,
            getHasNotDescriptionError(),
            isOnTheFly,
            new LocalQuickFix[] {getFix(module, descriptionDir)},
            ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
    return new ProblemDescriptor[] {problemDescriptor};
  }
 @Override
 protected void visitClassMemberReferenceElement(GrMember classMember, GrReferenceElement ref) {
   if (classMember != null && !willBeMoved(classMember, myMovedMembers)) {
     final PsiClass containingClass = classMember.getContainingClass();
     if (containingClass != null
         && !PsiUtil.isAccessibleFromPackage(classMember, myTargetPackage)
         && (classMember.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)
             || classMember.hasModifierProperty(PsiModifier.PROTECTED)
                 && !mySubClass.isInheritor(containingClass, true))) {
       myConflicts.putValue(
           myMember,
           RefactoringUIUtil.getDescription(classMember, true) + " won't be accessible");
     }
   }
 }
 @PsiUtil.AccessLevel
 private static int getEffectiveLevel(
     @NotNull PsiElement element,
     @NotNull PsiFile file,
     @NotNull PsiFile memberFile,
     PsiClass memberClass,
     PsiPackage memberPackage) {
   PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
   if (memberClass != null && PsiTreeUtil.isAncestor(aClass, memberClass, false)
       || aClass != null && PsiTreeUtil.isAncestor(memberClass, aClass, false)) {
     // access from the same file can be via private
     // except when used in annotation:
     // @Ann(value = C.VAL) class C { public static final String VAL = "xx"; }
     PsiAnnotation annotation = PsiTreeUtil.getParentOfType(element, PsiAnnotation.class);
     if (annotation != null
         && annotation.getParent() instanceof PsiModifierList
         && annotation.getParent().getParent() == aClass) {
       return PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL;
     }
     return PsiUtil.ACCESS_LEVEL_PRIVATE;
   }
   // if (file == memberFile) {
   //  return PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL;
   // }
   PsiDirectory directory = file.getContainingDirectory();
   PsiPackage aPackage =
       directory == null ? null : JavaDirectoryService.getInstance().getPackage(directory);
   if (aPackage == memberPackage
       || aPackage != null
           && memberPackage != null
           && Comparing.strEqual(
               aPackage.getQualifiedName(), memberPackage.getQualifiedName())) {
     return PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL;
   }
   if (aClass != null && memberClass != null && aClass.isInheritor(memberClass, true)) {
     // access from subclass can be via protected, except for constructors
     PsiElement resolved =
         element instanceof PsiReference ? ((PsiReference) element).resolve() : null;
     boolean isConstructor =
         resolved instanceof PsiClass && element.getParent() instanceof PsiNewExpression
             || resolved instanceof PsiMethod && ((PsiMethod) resolved).isConstructor();
     if (!isConstructor) {
       return PsiUtil.ACCESS_LEVEL_PROTECTED;
     }
   }
   return PsiUtil.ACCESS_LEVEL_PUBLIC;
 }
 private static void addResultFromReference(
     final PsiReference reference,
     final PsiClass methodClass,
     final PsiManager manager,
     final PsiClass aClass,
     final Processor<UsageInfo> results,
     final FindUsagesOptions options) {
   PsiElement refElement = reference.getElement();
   if (refElement instanceof PsiReferenceExpression) {
     PsiClass usedClass =
         getFieldOrMethodAccessedClass((PsiReferenceExpression) refElement, methodClass);
     if (usedClass != null) {
       if (manager.areElementsEquivalent(usedClass, aClass)
           || usedClass.isInheritor(aClass, true)) {
         addResult(results, refElement, options);
       }
     }
   }
 }
 public static boolean isJUnitTestCase(PsiClass aClass) {
   final Project project = aClass.getProject();
   final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
   final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
   final PsiClass testCase = psiFacade.findClass("junit.framework.TestCase", scope);
   if (testCase == null) {
     return false;
   }
   if (aClass.isInheritor(testCase, true)) {
     return true;
   }
   final PsiMethod[] methods = aClass.getMethods();
   for (PsiMethod method : methods) {
     //noinspection HardCodedStringLiteral
     if (AnnotationUtil.isAnnotated(method, "org.junit.Test", true)) {
       return true;
     }
   }
   return false;
 }
Exemple #22
0
    @Nullable
    private SiblingInfo findSibling(PsiClass inheritor, PsiClass anInterface, PsiMethod method) {
      for (PsiMethod superMethod : anInterface.findMethodsByName(method.getName(), true)) {
        PsiElement navigationElement = superMethod.getNavigationElement();
        if (!(navigationElement instanceof PsiMethod)) continue; // Kotlin
        superMethod = (PsiMethod) navigationElement;
        ProgressManager.checkCanceled();
        PsiClass superInterface = superMethod.getContainingClass();
        if (superInterface == null || myContainingClass.isInheritor(superInterface, true)) {
          // if containingClass implements the superInterface then it's not a sibling inheritance
          // but a pretty boring the usual one
          continue;
        }

        if (isOverridden(inheritor, method, superMethod, superInterface)) {
          return new SiblingInfo(superMethod, inheritor);
        }
      }
      return null;
    }
  @NotNull
  private static Collection<PsiClass> findRelatedActivities(
      @NotNull XmlFile file,
      @NotNull AndroidFacet facet,
      @NotNull DomFileDescription<?> description) {
    if (description instanceof LayoutDomFileDescription) {
      final Computable<List<GotoRelatedItem>> computable =
          AndroidGotoRelatedProvider.getLazyItemsForXmlFile(file, facet);

      if (computable == null) {
        return Collections.emptyList();
      }
      final List<GotoRelatedItem> items = computable.compute();

      if (items.isEmpty()) {
        return Collections.emptyList();
      }
      final PsiClass activityClass = findActivityClass(facet.getModule());

      if (activityClass == null) {
        return Collections.emptyList();
      }
      final List<PsiClass> result = new ArrayList<PsiClass>();

      for (GotoRelatedItem item : items) {
        final PsiElement element = item.getElement();

        if (element instanceof PsiClass) {
          final PsiClass aClass = (PsiClass) element;

          if (aClass.isInheritor(activityClass, true)) {
            result.add(aClass);
          }
        }
      }
      return result;
    } else {
      return findRelatedActivitiesForMenu(file, facet);
    }
  }
Exemple #24
0
  protected void initialize() {
    myDefaultConstructor = null;

    final PsiClass psiClass = getElement();

    LOG.assertTrue(psiClass != null);

    PsiElement psiParent = psiClass.getParent();
    if (psiParent instanceof PsiFile) {
      if (isSyntheticJSP()) {
        final RefFileImpl refFile =
            (RefFileImpl) getRefManager().getReference(JspPsiUtil.getJspFile(psiClass));
        LOG.assertTrue(refFile != null);
        refFile.add(this);
      } else if (psiParent instanceof PsiJavaFile) {
        PsiJavaFile psiFile = (PsiJavaFile) psiParent;
        String packageName = psiFile.getPackageName();
        if (!"".equals(packageName)) {
          ((RefPackageImpl) getRefJavaManager().getPackage(packageName)).add(this);
        } else {
          ((RefPackageImpl) getRefJavaManager().getDefaultPackage()).add(this);
        }
      }
      final Module module = ModuleUtil.findModuleForPsiElement(psiClass);
      LOG.assertTrue(module != null);
      final RefModuleImpl refModule = ((RefModuleImpl) getRefManager().getRefModule(module));
      LOG.assertTrue(refModule != null);
      refModule.add(this);
    } else {
      while (!(psiParent instanceof PsiClass
          || psiParent instanceof PsiMethod
          || psiParent instanceof PsiField)) {
        psiParent = psiParent.getParent();
      }
      RefElement refParent = getRefManager().getReference(psiParent);
      LOG.assertTrue(refParent != null);
      ((RefElementImpl) refParent).add(this);
    }

    setAbstract(psiClass.hasModifierProperty(PsiModifier.ABSTRACT));

    setAnonymous(psiClass instanceof PsiAnonymousClass);
    setIsLocal(!(isAnonymous() || psiParent instanceof PsiClass || psiParent instanceof PsiFile));
    setInterface(psiClass.isInterface());

    initializeSuperReferences(psiClass);

    PsiMethod[] psiMethods = psiClass.getMethods();
    PsiField[] psiFields = psiClass.getFields();

    setUtilityClass(psiMethods.length > 0 || psiFields.length > 0);

    for (PsiField psiField : psiFields) {
      getRefManager().getReference(psiField);
    }

    if (!isApplet()) {
      final PsiClass servlet = getRefJavaManager().getServlet();
      setServlet(servlet != null && psiClass.isInheritor(servlet, true));
    }
    if (!isApplet() && !isServlet()) {
      setTestCase(TestUtil.isTestClass(psiClass));
      for (RefClass refBase : getBaseClasses()) {
        ((RefClassImpl) refBase).setTestCase(true);
      }
    }

    for (PsiMethod psiMethod : psiMethods) {
      RefMethod refMethod = (RefMethod) getRefManager().getReference(psiMethod);

      if (refMethod != null) {
        if (psiMethod.isConstructor()) {
          if (psiMethod.getParameterList().getParametersCount() > 0
              || !psiMethod.hasModifierProperty(PsiModifier.PRIVATE)) {
            setUtilityClass(false);
          }

          addConstructor(refMethod);
          if (psiMethod.getParameterList().getParametersCount() == 0) {
            setDefaultConstructor((RefMethodImpl) refMethod);
          }
        } else {
          if (!psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
            setUtilityClass(false);
          }
        }
      }
    }

    if (getConstructors().size() == 0 && !isInterface() && !isAnonymous()) {
      RefImplicitConstructorImpl refImplicitConstructor = new RefImplicitConstructorImpl(this);
      setDefaultConstructor(refImplicitConstructor);
      addConstructor(refImplicitConstructor);
    }

    if (isInterface()) {
      for (int i = 0; i < psiFields.length && isUtilityClass(); i++) {
        PsiField psiField = psiFields[i];
        if (!psiField.hasModifierProperty(PsiModifier.STATIC)) {
          setUtilityClass(false);
        }
      }
    }

    final PsiClass applet = getRefJavaManager().getApplet();
    setApplet(applet != null && psiClass.isInheritor(applet, true));
    getRefManager().fireNodeInitialized(this);
  }
  private static Map<MethodSignature, HierarchicalMethodSignature> buildMethodHierarchy(
      PsiClass aClass,
      PsiSubstitutor substitutor,
      final boolean includePrivates,
      final Set<PsiClass> visited,
      boolean isInRawContext) {
    Map<MethodSignature, HierarchicalMethodSignature> result =
        new LinkedHashMap<MethodSignature, HierarchicalMethodSignature>();
    final Map<MethodSignature, List<PsiMethod>> sameParameterErasureMethods =
        new THashMap<MethodSignature, List<PsiMethod>>(
            MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);

    Map<MethodSignature, HierarchicalMethodSignatureImpl> map =
        new THashMap<MethodSignature, HierarchicalMethodSignatureImpl>(
            new TObjectHashingStrategy<MethodSignature>() {
              @Override
              public int computeHashCode(MethodSignature signature) {
                return MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.computeHashCode(
                    signature);
              }

              @Override
              public boolean equals(MethodSignature o1, MethodSignature o2) {
                if (!MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY.equals(o1, o2))
                  return false;
                List<PsiMethod> list = sameParameterErasureMethods.get(o1);
                boolean toCheckReturnType = list != null && list.size() > 1;
                if (!toCheckReturnType) return true;
                PsiType returnType1 =
                    ((MethodSignatureBackedByPsiMethod) o1).getMethod().getReturnType();
                PsiType returnType2 =
                    ((MethodSignatureBackedByPsiMethod) o2).getMethod().getReturnType();
                if (returnType1 == null && returnType2 == null) return true;
                if (returnType1 == null || returnType2 == null) return false;

                PsiType erasure1 =
                    TypeConversionUtil.erasure(o1.getSubstitutor().substitute(returnType1));
                PsiType erasure2 =
                    TypeConversionUtil.erasure(o2.getSubstitutor().substitute(returnType2));
                return erasure1.equals(erasure2);
              }
            });

    for (PsiMethod method : aClass.getMethods()) {
      if (!method.isValid()) {
        throw new PsiInvalidElementAccessException(
            method, "class.valid=" + aClass.isValid() + "; name=" + method.getName());
      }
      if (!includePrivates && method.hasModifierProperty(PsiModifier.PRIVATE)) continue;
      final MethodSignatureBackedByPsiMethod signature =
          MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext);
      HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(signature);

      List<PsiMethod> list = sameParameterErasureMethods.get(signature);
      if (list == null) {
        list = new SmartList<PsiMethod>();
        sameParameterErasureMethods.put(signature, list);
      }
      list.add(method);

      LOG.assertTrue(newH.getMethod().isValid());
      result.put(signature, newH);
      map.put(signature, newH);
    }

    for (PsiClassType superType : aClass.getSuperTypes()) {
      PsiClassType.ClassResolveResult superTypeResolveResult = superType.resolveGenerics();
      PsiClass superClass = superTypeResolveResult.getElement();
      if (superClass == null) continue;
      if (!visited.add(superClass)) continue; // cyclic inheritance
      final PsiSubstitutor superSubstitutor = superTypeResolveResult.getSubstitutor();
      PsiSubstitutor finalSubstitutor =
          obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext);

      final boolean isInRawContextSuper =
          (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor))
              && superClass.getTypeParameters().length != 0;
      Map<MethodSignature, HierarchicalMethodSignature> superResult =
          buildMethodHierarchy(superClass, finalSubstitutor, false, visited, isInRawContextSuper);
      visited.remove(superClass);

      List<Pair<MethodSignature, HierarchicalMethodSignature>> flattened =
          new ArrayList<Pair<MethodSignature, HierarchicalMethodSignature>>();
      for (Map.Entry<MethodSignature, HierarchicalMethodSignature> entry : superResult.entrySet()) {
        HierarchicalMethodSignature hms = entry.getValue();
        MethodSignature signature = entry.getKey();
        PsiClass containingClass = hms.getMethod().getContainingClass();
        List<HierarchicalMethodSignature> supers =
            new ArrayList<HierarchicalMethodSignature>(hms.getSuperSignatures());
        for (HierarchicalMethodSignature aSuper : supers) {
          PsiClass superContainingClass = aSuper.getMethod().getContainingClass();
          if (containingClass != null
              && superContainingClass != null
              && !containingClass.isInheritor(superContainingClass, true)) {
            // methods must be inherited from unrelated classes, so flatten hierarchy here
            // class C implements SAM1, SAM2 { void methodimpl() {} }
            // hms.getSuperSignatures().remove(aSuper);
            flattened.add(
                new Pair<MethodSignature, HierarchicalMethodSignature>(signature, aSuper));
          }
        }
        putInMap(aClass, result, map, hms, signature);
      }
      for (Pair<MethodSignature, HierarchicalMethodSignature> pair : flattened) {
        putInMap(aClass, result, map, pair.second, pair.first);
      }
    }

    for (Map.Entry<MethodSignature, HierarchicalMethodSignatureImpl> entry : map.entrySet()) {
      HierarchicalMethodSignatureImpl hierarchicalMethodSignature = entry.getValue();
      MethodSignature methodSignature = entry.getKey();
      if (result.get(methodSignature) == null
          && PsiUtil.isAccessible(
              aClass.getProject(), hierarchicalMethodSignature.getMethod(), aClass, aClass)) {
        LOG.assertTrue(hierarchicalMethodSignature.getMethod().isValid());
        result.put(methodSignature, hierarchicalMethodSignature);
      }
    }

    return result;
  }
  protected void generateFindViewById() {
    PsiClass activityClass =
        JavaPsiFacade.getInstance(mProject)
            .findClass("android.app.Activity", new EverythingGlobalScope(mProject));
    PsiClass compatActivityClass =
        JavaPsiFacade.getInstance(mProject)
            .findClass(
                "android.support.v7.app.AppCompatActivity", new EverythingGlobalScope(mProject));
    PsiClass fragmentClass =
        JavaPsiFacade.getInstance(mProject)
            .findClass("android.app.Fragment", new EverythingGlobalScope(mProject));
    PsiClass supportFragmentClass =
        JavaPsiFacade.getInstance(mProject)
            .findClass("android.support.v4.app.Fragment", new EverythingGlobalScope(mProject));

    // Check for Activity class
    if ((activityClass != null && mClass.isInheritor(activityClass, true))
        || (compatActivityClass != null && mClass.isInheritor(compatActivityClass, true))
        || mClass.getName().contains("Activity")) {
      if (mClass.findMethodsByName("onCreate", false).length == 0) {
        // Add an empty stub of onCreate()
        StringBuilder method = new StringBuilder();
        method.append(
            "@Override protected void onCreate(android.os.Bundle savedInstanceState) {\n");
        method.append("super.onCreate(savedInstanceState);\n");
        method.append("\t// TODO: add setContentView(...) and run LayoutCreator again\n");
        method.append("}");

        mClass.add(mFactory.createMethodFromText(method.toString(), mClass));
      } else {
        PsiStatement setContentViewStatement = null;
        boolean hasInitViewStatement = false;

        PsiMethod onCreate = mClass.findMethodsByName("onCreate", false)[0];
        for (PsiStatement statement : onCreate.getBody().getStatements()) {
          // Search for setContentView()
          if (statement.getFirstChild() instanceof PsiMethodCallExpression) {
            PsiReferenceExpression methodExpression =
                ((PsiMethodCallExpression) statement.getFirstChild()).getMethodExpression();
            if (methodExpression.getText().equals("setContentView")) {
              setContentViewStatement = statement;
            } else if (methodExpression.getText().equals("initView")) {
              hasInitViewStatement = true;
            }
          }
        }

        if (!hasInitViewStatement && setContentViewStatement != null) {
          // Insert initView() after setContentView()
          onCreate
              .getBody()
              .addAfter(
                  mFactory.createStatementFromText("initView();", mClass), setContentViewStatement);
        }
        generatorLayoutCode("this", null);
      }
      // Check for Fragment class
    } else if ((fragmentClass != null && mClass.isInheritor(fragmentClass, true))
        || (supportFragmentClass != null && mClass.isInheritor(supportFragmentClass, true))) {
      if (mClass.findMethodsByName("onCreateView", false).length == 0) {
        // Add an empty stub of onCreateView()
        StringBuilder method = new StringBuilder();
        method.append(
            "@Override public View onCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup container, android.os.Bundle savedInstanceState) {\n");
        method.append(
            "\t// TODO: inflate a fragment like bottom ... and run LayoutCreator again\n");
        method.append("View view = View.inflate(getActivity(), R.layout.frag_layout, null);");
        method.append("return view;");
        method.append("}");
        mClass.add(mFactory.createMethodFromText(method.toString(), mClass));
      } else {
        PsiReturnStatement returnStatement = null;
        String returnValue = null;
        boolean hasInitViewStatement = false;
        PsiMethod onCreateView = mClass.findMethodsByName("onCreateView", false)[0];
        for (PsiStatement statement : onCreateView.getBody().getStatements()) {
          if (statement instanceof PsiReturnStatement) {
            returnStatement = (PsiReturnStatement) statement;
            returnValue = returnStatement.getReturnValue().getText();
          } else if (statement.getFirstChild() instanceof PsiMethodCallExpression) {
            PsiReferenceExpression methodExpression =
                ((PsiMethodCallExpression) statement.getFirstChild()).getMethodExpression();
            if (methodExpression.getText().equals("initView")) {
              hasInitViewStatement = true;
            }
          }
        }

        if (!hasInitViewStatement && returnStatement != null && returnValue != null) {
          // Insert initView() before return statement
          onCreateView
              .getBody()
              .addBefore(
                  mFactory.createStatementFromText("initView(" + returnValue + ");", mClass),
                  returnStatement);
        }
        generatorLayoutCode("getContext()", returnValue);
      }
    }
  }
Exemple #27
0
  @Override
  public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
    if (!LambdaUtil.isFunctionalType(myT)) {
      return false;
    }

    final PsiType groundTargetType =
        FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT);
    final PsiClassType.ClassResolveResult classResolveResult =
        PsiUtil.resolveGenericsClassInType(groundTargetType);
    final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(classResolveResult);
    if (interfaceMethod == null) {
      return false;
    }

    final PsiSubstitutor substitutor =
        LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult);
    final PsiParameter[] targetParameters = interfaceMethod.getParameterList().getParameters();
    final PsiType interfaceMethodReturnType = interfaceMethod.getReturnType();
    final PsiType returnType = substitutor.substitute(interfaceMethodReturnType);
    final PsiType[] typeParameters = myExpression.getTypeParameters();

    final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult =
        PsiMethodReferenceUtil.getQualifierResolveResult(myExpression);

    if (!myExpression.isExact()) {
      for (PsiParameter parameter : targetParameters) {
        if (!session.isProperType(substitutor.substitute(parameter.getType()))) {
          return false;
        }
      }
    } else {
      final PsiMember applicableMember = myExpression.getPotentiallyApplicableMember();
      LOG.assertTrue(applicableMember != null);

      final PsiClass applicableMemberContainingClass = applicableMember.getContainingClass();
      final PsiClass containingClass = qualifierResolveResult.getContainingClass();

      PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
      psiSubstitutor =
          applicableMemberContainingClass == null
                  || containingClass == null
                  || myExpression.isConstructor()
              ? psiSubstitutor
              : TypeConversionUtil.getSuperClassSubstitutor(
                  applicableMemberContainingClass, containingClass, psiSubstitutor);

      PsiType applicableMethodReturnType =
          applicableMember instanceof PsiMethod
              ? ((PsiMethod) applicableMember).getReturnType()
              : null;
      int idx = 0;
      for (PsiTypeParameter param :
          ((PsiTypeParameterListOwner) applicableMember).getTypeParameters()) {
        if (idx < typeParameters.length) {
          psiSubstitutor = psiSubstitutor.put(param, typeParameters[idx++]);
        }
      }
      final PsiParameter[] parameters =
          applicableMember instanceof PsiMethod
              ? ((PsiMethod) applicableMember).getParameterList().getParameters()
              : PsiParameter.EMPTY_ARRAY;
      if (targetParameters.length == parameters.length + 1) {
        specialCase(session, constraints, substitutor, targetParameters, true);
        for (int i = 1; i < targetParameters.length; i++) {
          constraints.add(
              new TypeCompatibilityConstraint(
                  session.substituteWithInferenceVariables(
                      psiSubstitutor.substitute(parameters[i - 1].getType())),
                  substitutor.substitute(targetParameters[i].getType())));
        }
      } else if (targetParameters.length == parameters.length) {
        for (int i = 0; i < targetParameters.length; i++) {
          constraints.add(
              new TypeCompatibilityConstraint(
                  session.substituteWithInferenceVariables(
                      psiSubstitutor.substitute(parameters[i].getType())),
                  substitutor.substitute(targetParameters[i].getType())));
        }
      } else {
        return false;
      }
      if (returnType != PsiType.VOID && returnType != null) {
        if (applicableMethodReturnType == PsiType.VOID) {
          return false;
        }

        if (applicableMethodReturnType != null) {
          constraints.add(
              new TypeCompatibilityConstraint(
                  returnType,
                  session.substituteWithInferenceVariables(
                      psiSubstitutor.substitute(applicableMethodReturnType))));
        } else if (applicableMember instanceof PsiClass
            || applicableMember instanceof PsiMethod
                && ((PsiMethod) applicableMember).isConstructor()) {
          final PsiElementFactory elementFactory =
              JavaPsiFacade.getElementFactory(applicableMember.getProject());
          if (containingClass != null) {
            final PsiType classType =
                session.substituteWithInferenceVariables(
                    elementFactory.createType(containingClass, psiSubstitutor));
            constraints.add(new TypeCompatibilityConstraint(returnType, classType));
          }
        }
      }
      return true;
    }

    final Map<PsiElement, PsiType> map = LambdaUtil.getFunctionalTypeMap();
    final PsiType added = map.put(myExpression, session.startWithFreshVars(groundTargetType));
    final JavaResolveResult resolve;
    try {
      resolve = myExpression.advancedResolve(true);
    } finally {
      if (added == null) {
        map.remove(myExpression);
      }
    }
    final PsiElement element = resolve.getElement();
    if (element == null) {
      return false;
    }

    if (PsiType.VOID.equals(returnType) || returnType == null) {
      return true;
    }

    if (element instanceof PsiMethod) {
      final PsiMethod method = (PsiMethod) element;
      final PsiType referencedMethodReturnType;
      final PsiClass containingClass = method.getContainingClass();
      LOG.assertTrue(containingClass != null, method);
      PsiClass qContainingClass = qualifierResolveResult.getContainingClass();
      PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
      if (qContainingClass != null) {
        if (PsiUtil.isRawSubstitutor(qContainingClass, psiSubstitutor)) {
          psiSubstitutor = PsiSubstitutor.EMPTY;
        }
        if (qContainingClass.isInheritor(containingClass, true)) {
          psiSubstitutor =
              TypeConversionUtil.getClassSubstitutor(
                  containingClass, qContainingClass, PsiSubstitutor.EMPTY);
          LOG.assertTrue(psiSubstitutor != null);
        }
      }

      if (method.isConstructor()) {
        referencedMethodReturnType =
            JavaPsiFacade.getElementFactory(method.getProject())
                .createType(containingClass, PsiSubstitutor.EMPTY);
      } else {
        referencedMethodReturnType = method.getReturnType();
      }
      LOG.assertTrue(referencedMethodReturnType != null, method);

      if (!PsiTreeUtil.isContextAncestor(containingClass, myExpression, false)
          || PsiUtil.getEnclosingStaticElement(myExpression, containingClass) != null) {
        session.initBounds(myExpression, containingClass.getTypeParameters());
      }

      session.initBounds(myExpression, method.getTypeParameters());

      // if i) the method reference elides NonWildTypeArguments,
      //  ii) the compile-time declaration is a generic method, and
      // iii) the return type of the compile-time declaration mentions at least one of the method's
      // type parameters;
      if (typeParameters.length == 0 && method.getTypeParameters().length > 0) {
        final PsiClass interfaceClass = classResolveResult.getElement();
        LOG.assertTrue(interfaceClass != null);
        if (PsiPolyExpressionUtil.mentionsTypeParameters(
            referencedMethodReturnType, ContainerUtil.newHashSet(method.getTypeParameters()))) {
          // the constraint reduces to the bound set B3 which would be used to determine the method
          // reference's invocation type
          // when targeting the return type of the function type, as defined in 18.5.2.
          session.collectApplicabilityConstraints(
              myExpression, ((MethodCandidateInfo) resolve), groundTargetType);
          session.registerReturnTypeConstraints(referencedMethodReturnType, returnType);
          return true;
        }
      }

      if (PsiType.VOID.equals(referencedMethodReturnType)) {
        return false;
      }

      int idx = 0;
      for (PsiTypeParameter param : method.getTypeParameters()) {
        if (idx < typeParameters.length) {
          psiSubstitutor = psiSubstitutor.put(param, typeParameters[idx++]);
        }
      }

      final PsiParameter[] parameters = method.getParameterList().getParameters();
      if (targetParameters.length == parameters.length + 1
          && !method.isVarArgs()
          && PsiPolyExpressionUtil.mentionsTypeParameters(
              referencedMethodReturnType,
              ContainerUtil.newHashSet(
                  containingClass.getTypeParameters()))) { // todo specification bug?
        specialCase(session, constraints, substitutor, targetParameters, false);
      }
      constraints.add(
          new TypeCompatibilityConstraint(
              returnType,
              session.substituteWithInferenceVariables(
                  psiSubstitutor.substitute(referencedMethodReturnType))));
    }

    return true;
  }
  private Domination dominates(
      PsiClass aClass, boolean accessible, String fqName, ClassCandidateInfo info) {
    final PsiClass otherClass = info.getElement();
    assert otherClass != null;
    String otherQName = otherClass.getQualifiedName();
    if (fqName.equals(otherQName)) {
      return Domination.DOMINATED_BY;
    }

    final PsiClass containingClass1 = aClass.getContainingClass();
    final PsiClass containingClass2 = otherClass.getContainingClass();
    if (myAccessClass != null && !Comparing.equal(containingClass1, containingClass2)) {
      if (myAccessClass.equals(containingClass1)) return Domination.DOMINATES;
      if (myAccessClass.equals(containingClass2)) return Domination.DOMINATED_BY;
    }

    // JLS 8.5:
    // A class may inherit two or more type declarations with the same name, either from two
    // interfaces or from its superclass and an interface.
    // It is a compile-time error to attempt to refer to any ambiguously inherited class or
    // interface by its simple name.
    if (containingClass1 != null
        && containingClass2 != null
        && containingClass2.isInheritor(containingClass1, true)
        && !isImported(myCurrentFileContext)) {
      if (!isAmbiguousInherited(containingClass1)) {
        // shadowing
        return Domination.DOMINATED_BY;
      }
    }

    boolean infoAccessible = info.isAccessible() && isAccessible(otherClass);
    if (infoAccessible && !accessible) {
      return Domination.DOMINATED_BY;
    }
    if (!infoAccessible && accessible) {
      return Domination.DOMINATES;
    }

    // everything wins over class from default package
    boolean isDefault = StringUtil.getPackageName(fqName).length() == 0;
    boolean otherDefault =
        otherQName != null && StringUtil.getPackageName(otherQName).length() == 0;
    if (isDefault && !otherDefault) {
      return Domination.DOMINATED_BY;
    }
    if (!isDefault && otherDefault) {
      return Domination.DOMINATES;
    }

    // single import wins over on-demand
    boolean myOnDemand = isOnDemand(myCurrentFileContext, aClass);
    boolean otherOnDemand = isOnDemand(info.getCurrentFileResolveScope(), otherClass);
    if (myOnDemand && !otherOnDemand) {
      return Domination.DOMINATED_BY;
    }
    if (!myOnDemand && otherOnDemand) {
      return Domination.DOMINATES;
    }

    return Domination.EQUAL;
  }
  @NotNull
  private static LookupElement castQualifier(
      @NotNull LookupElement item,
      @Nullable final PsiTypeLookupItem castTypeItem,
      @Nullable PsiType plainQualifier,
      JavaCompletionProcessor processor) {
    if (castTypeItem == null) {
      return item;
    }
    if (plainQualifier != null) {
      Object o = item.getObject();
      if (o instanceof PsiMethod) {
        PsiType castType = castTypeItem.getType();
        if (plainQualifier instanceof PsiClassType && castType instanceof PsiClassType) {
          PsiMethod method = (PsiMethod) o;
          PsiClassType.ClassResolveResult plainResult =
              ((PsiClassType) plainQualifier).resolveGenerics();
          PsiClass plainClass = plainResult.getElement();
          if (plainClass != null && plainClass.findMethodBySignature(method, true) != null) {
            PsiClass castClass = ((PsiClassType) castType).resolveGenerics().getElement();

            if (castClass == null || !castClass.isInheritor(plainClass, true)) {
              return item;
            }

            PsiSubstitutor plainSub = plainResult.getSubstitutor();
            PsiSubstitutor castSub =
                TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType) castType);
            PsiType returnType = method.getReturnType();
            if (method.getSignature(plainSub).equals(method.getSignature(castSub))) {
              PsiType typeAfterCast = toRaw(castSub.substitute(returnType));
              PsiType typeDeclared = toRaw(plainSub.substitute(returnType));
              if (typeAfterCast != null
                  && typeDeclared != null
                  && typeAfterCast.isAssignableFrom(typeDeclared)
                  && processor.isAccessible(plainClass.findMethodBySignature(method, true))) {
                return item;
              }
            }
          }
        }
      } else if (containsMember(plainQualifier, o)) {
        return item;
      }
    }

    return LookupElementDecorator.withInsertHandler(
        item,
        new InsertHandlerDecorator<LookupElement>() {
          @Override
          public void handleInsert(
              InsertionContext context, LookupElementDecorator<LookupElement> item) {
            final Document document = context.getEditor().getDocument();
            context.commitDocument();
            final PsiFile file = context.getFile();
            final PsiJavaCodeReferenceElement ref =
                PsiTreeUtil.findElementOfClassAtOffset(
                    file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false);
            if (ref != null) {
              final PsiElement qualifier = ref.getQualifier();
              if (qualifier != null) {
                final CommonCodeStyleSettings settings = context.getCodeStyleSettings();

                final String parenSpace = settings.SPACE_WITHIN_PARENTHESES ? " " : "";
                document.insertString(qualifier.getTextRange().getEndOffset(), parenSpace + ")");

                final String spaceWithin = settings.SPACE_WITHIN_CAST_PARENTHESES ? " " : "";
                final String prefix = "(" + parenSpace + "(" + spaceWithin;
                final String spaceAfter = settings.SPACE_AFTER_TYPE_CAST ? " " : "";
                final int exprStart = qualifier.getTextRange().getStartOffset();
                document.insertString(exprStart, prefix + spaceWithin + ")" + spaceAfter);

                CompletionUtil.emulateInsertion(context, exprStart + prefix.length(), castTypeItem);
                PsiDocumentManager.getInstance(file.getProject())
                    .doPostponedOperationsAndUnblockDocument(document);
                context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
              }
            }

            item.getDelegate().handleInsert(context);
          }
        });
  }
  private Specifics isMoreSpecific(
      @NotNull MethodCandidateInfo info1,
      @NotNull MethodCandidateInfo info2,
      @MethodCandidateInfo.ApplicabilityLevelConstant int applicabilityLevel,
      @NotNull LanguageLevel languageLevel) {
    PsiMethod method1 = info1.getElement();
    PsiMethod method2 = info2.getElement();
    final PsiClass class1 = method1.getContainingClass();
    final PsiClass class2 = method2.getContainingClass();

    final PsiParameter[] params1 = method1.getParameterList().getParameters();
    final PsiParameter[] params2 = method2.getParameterList().getParameters();

    final PsiTypeParameter[] typeParameters1 = method1.getTypeParameters();
    final PsiTypeParameter[] typeParameters2 = method2.getTypeParameters();
    final PsiSubstitutor classSubstitutor1 =
        info1.getSubstitutor(false); // substitutions for method type parameters will be ignored
    final PsiSubstitutor classSubstitutor2 = info2.getSubstitutor(false);

    final int max = Math.max(params1.length, params2.length);
    PsiType[] types1 = PsiType.createArray(max);
    PsiType[] types2 = PsiType.createArray(max);
    final boolean varargsPosition =
        applicabilityLevel == MethodCandidateInfo.ApplicabilityLevel.VARARGS;
    for (int i = 0; i < max; i++) {
      ProgressManager.checkCanceled();
      PsiType type1 =
          params1.length > 0 ? params1[Math.min(i, params1.length - 1)].getType() : null;
      PsiType type2 =
          params2.length > 0 ? params2[Math.min(i, params2.length - 1)].getType() : null;
      if (varargsPosition) {
        if (type1 instanceof PsiEllipsisType
            && type2 instanceof PsiEllipsisType
            && params1.length == params2.length
            && class1 != null
            && (!JavaVersionService.getInstance().isAtLeast(class1, JavaSdkVersion.JDK_1_7)
                || ((PsiArrayType) type1)
                    .getComponentType()
                    .equalsToText(CommonClassNames.JAVA_LANG_OBJECT)
                || ((PsiArrayType) type2)
                    .getComponentType()
                    .equalsToText(CommonClassNames.JAVA_LANG_OBJECT))) {
          type1 = ((PsiEllipsisType) type1).toArrayType();
          type2 = ((PsiEllipsisType) type2).toArrayType();
        } else {
          type1 =
              type1 instanceof PsiEllipsisType ? ((PsiArrayType) type1).getComponentType() : type1;
          type2 =
              type2 instanceof PsiEllipsisType ? ((PsiArrayType) type2).getComponentType() : type2;
        }
      }

      types1[i] = type1;
      types2[i] = type2;
    }

    boolean sameBoxing = true;
    int[] boxingHappened = new int[2];
    for (int i = 0; i < types1.length; i++) {
      ProgressManager.checkCanceled();
      PsiType type1 = classSubstitutor1.substitute(types1[i]);
      PsiType type2 = classSubstitutor2.substitute(types2[i]);
      PsiType argType = i < getActualParameterTypes().length ? getActualParameterTypes()[i] : null;

      boolean boxingInFirst = false;
      if (isBoxingHappened(argType, type1, languageLevel)) {
        boxingHappened[0] += 1;
        boxingInFirst = true;
      }

      boolean boxingInSecond = false;
      if (isBoxingHappened(argType, type2, languageLevel)) {
        boxingHappened[1] += 1;
        boxingInSecond = true;
      }
      sameBoxing &= boxingInFirst == boxingInSecond;
    }
    if (boxingHappened[0] == 0 && boxingHappened[1] > 0) return Specifics.FIRST;
    if (boxingHappened[0] > 0 && boxingHappened[1] == 0) return Specifics.SECOND;

    if (sameBoxing) {
      final PsiSubstitutor siteSubstitutor1 = info1.getSiteSubstitutor();
      final PsiSubstitutor siteSubstitutor2 = info2.getSiteSubstitutor();

      final PsiType[] types2AtSite = typesAtSite(types2, siteSubstitutor2);
      final PsiType[] types1AtSite = typesAtSite(types1, siteSubstitutor1);

      final PsiSubstitutor methodSubstitutor1 =
          calculateMethodSubstitutor(
              typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel);
      boolean applicable12 =
          isApplicableTo(
              types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2);

      final PsiSubstitutor methodSubstitutor2 =
          calculateMethodSubstitutor(
              typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel);
      boolean applicable21 =
          isApplicableTo(
              types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1);

      if (!myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
        final boolean typeArgsApplicable12 =
            GenericsUtil.isTypeArgumentsApplicable(
                typeParameters1, methodSubstitutor1, myArgumentsList, !applicable21);
        final boolean typeArgsApplicable21 =
            GenericsUtil.isTypeArgumentsApplicable(
                typeParameters2, methodSubstitutor2, myArgumentsList, !applicable12);

        if (!typeArgsApplicable12) {
          applicable12 = false;
        }

        if (!typeArgsApplicable21) {
          applicable21 = false;
        }
      }

      if (applicable12 || applicable21) {

        if (applicable12 && !applicable21) return Specifics.SECOND;
        if (applicable21 && !applicable12) return Specifics.FIRST;

        final boolean abstract1 = method1.hasModifierProperty(PsiModifier.ABSTRACT);
        final boolean abstract2 = method2.hasModifierProperty(PsiModifier.ABSTRACT);
        if (abstract1 && !abstract2) {
          return Specifics.SECOND;
        }
        if (abstract2 && !abstract1) {
          return Specifics.FIRST;
        }
      }

      if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)
          && myArgumentsList instanceof PsiExpressionList
          && (typeParameters1.length == 0 || typeParameters2.length == 0)) {
        boolean toCompareFunctional = false;
        if (types1.length > 0 && types2.length > 0) {
          for (int i = 0; i < getActualParametersLength(); i++) {
            final PsiType type1 = types1[Math.min(i, types1.length - 1)];
            final PsiType type2 = types2[Math.min(i, types2.length - 1)];
            // from 15.12.2.5 Choosing the Most Specific Method
            // In addition, a functional interface type S is more specific than a functional
            // interface type T for an expression exp
            // if T is not a subtype of S and one of the following conditions apply.
            if (LambdaUtil.isFunctionalType(type1)
                && !TypeConversionUtil.erasure(type1).isAssignableFrom(type2)
                && LambdaUtil.isFunctionalType(type2)
                && !TypeConversionUtil.erasure(type2).isAssignableFrom(type1)) {
              types1AtSite[Math.min(i, types1.length - 1)] = PsiType.NULL;
              types2AtSite[Math.min(i, types2.length - 1)] = PsiType.NULL;
              toCompareFunctional = true;
            }
          }
        }

        if (toCompareFunctional) {
          final boolean applicable12ignoreFunctionalType =
              isApplicableTo(
                  types2AtSite,
                  method1,
                  languageLevel,
                  varargsPosition,
                  calculateMethodSubstitutor(
                      typeParameters1,
                      method1,
                      siteSubstitutor1,
                      types1,
                      types2AtSite,
                      languageLevel),
                  null);
          final boolean applicable21ignoreFunctionalType =
              isApplicableTo(
                  types1AtSite,
                  method2,
                  languageLevel,
                  varargsPosition,
                  calculateMethodSubstitutor(
                      typeParameters2,
                      method2,
                      siteSubstitutor2,
                      types2,
                      types1AtSite,
                      languageLevel),
                  null);

          if (applicable12ignoreFunctionalType || applicable21ignoreFunctionalType) {
            Specifics specifics = null;
            for (int i = 0; i < getActualParametersLength(); i++) {
              if (types1AtSite[Math.min(i, types1.length - 1)] == PsiType.NULL
                  && types2AtSite[Math.min(i, types2.length - 1)] == PsiType.NULL) {
                Specifics specific =
                    isFunctionalTypeMoreSpecific(
                        info1, info2, ((PsiExpressionList) myArgumentsList).getExpressions()[i], i);
                if (specific == Specifics.NEITHER) {
                  specifics = Specifics.NEITHER;
                  break;
                }

                if (specifics == null) {
                  specifics = specific;
                } else if (specifics != specific) {
                  specifics = Specifics.NEITHER;
                  break;
                }
              }
            }

            if (!applicable12ignoreFunctionalType && applicable21ignoreFunctionalType) {
              return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER;
            }

            if (!applicable21ignoreFunctionalType && applicable12ignoreFunctionalType) {
              return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER;
            }

            return specifics;
          }
        }
      }
    } else if (varargsPosition) {
      final PsiType lastParamType1 = classSubstitutor1.substitute(types1[types1.length - 1]);
      final PsiType lastParamType2 = classSubstitutor2.substitute(types2[types1.length - 1]);
      final boolean assignable1 = TypeConversionUtil.isAssignable(lastParamType2, lastParamType1);
      final boolean assignable2 = TypeConversionUtil.isAssignable(lastParamType1, lastParamType2);
      if (assignable1 && !assignable2) {
        return Specifics.FIRST;
      }
      if (assignable2 && !assignable1) {
        return Specifics.SECOND;
      }
    }

    if (class1 != class2) {
      if (class2.isInheritor(class1, true) || class1.isInterface() && !class2.isInterface()) {
        if (MethodSignatureUtil.isSubsignature(
            method1.getSignature(info1.getSubstitutor(false)),
            method2.getSignature(info2.getSubstitutor(false)))) {
          return Specifics.SECOND;
        } else if (method1.hasModifierProperty(PsiModifier.STATIC)
            && method2.hasModifierProperty(PsiModifier.STATIC)
            && boxingHappened[0] == 0) {
          return Specifics.SECOND;
        }
      } else if (MethodSignatureUtil.areErasedParametersEqual(
              method1.getSignature(PsiSubstitutor.EMPTY),
              method2.getSignature(PsiSubstitutor.EMPTY))
          && MethodSignatureUtil.isSubsignature(
              method2.getSignature(info2.getSubstitutor(false)),
              method1.getSignature(info1.getSubstitutor(false)))) {
        return Specifics.FIRST;
      } else if (class1.isInheritor(class2, true) || class2.isInterface()) {
        if (method1.hasModifierProperty(PsiModifier.STATIC)
            && method2.hasModifierProperty(PsiModifier.STATIC)
            && boxingHappened[0] == 0) {
          return Specifics.FIRST;
        }
      }
    }

    final boolean raw1 = PsiUtil.isRawSubstitutor(method1, classSubstitutor1);
    final boolean raw2 = PsiUtil.isRawSubstitutor(method2, classSubstitutor2);
    if (raw1 ^ raw2) {
      return raw1 ? Specifics.SECOND : Specifics.FIRST;
    }

    final boolean varargs1 = info1.isVarargs();
    final boolean varargs2 = info2.isVarargs();
    if (varargs1 ^ varargs2) {
      return varargs1 ? Specifics.SECOND : Specifics.FIRST;
    }

    return Specifics.NEITHER;
  }