private static boolean isClassAccepted(
      final PsiClass clazz,
      @Nullable final ClassKind classKind,
      final boolean instantiatable,
      final boolean concrete,
      final boolean notInterface,
      final boolean notEnum) {
    if (classKind == ClassKind.ANNOTATION) return clazz.isAnnotationType();
    if (classKind == ClassKind.ENUM) return clazz.isEnum();

    if (instantiatable) {
      if (PsiUtil.isInstantiatable(clazz)) {
        return true;
      }
    } else if (concrete) {
      if (!clazz.hasModifierProperty(PsiModifier.ABSTRACT) && !clazz.isInterface()) {
        return true;
      }
    } else if (notInterface) {
      if (!clazz.isInterface()) {
        return true;
      }
    } else if (notEnum) {
      if (!clazz.isEnum()) {
        return true;
      }
    } else {
      return true;
    }
    return false;
  }
  @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;
  }
  @NotNull
  private static PsiClass[] getSupersInner(@NotNull PsiClass psiClass) {
    PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes();
    PsiClassType[] implementsListTypes = psiClass.getImplementsListTypes();

    if (psiClass.isInterface()) {
      return resolveClassReferenceList(
          extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), true);
    }

    if (psiClass instanceof PsiAnonymousClass) {
      PsiAnonymousClass psiAnonymousClass = (PsiAnonymousClass) psiClass;
      PsiClassType baseClassReference = psiAnonymousClass.getBaseClassType();
      PsiClass baseClass = baseClassReference.resolve();
      if (baseClass != null) {
        if (baseClass.isInterface()) {
          PsiClass objectClass =
              JavaPsiFacade.getInstance(psiClass.getProject())
                  .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope());
          return objectClass != null
              ? new PsiClass[] {objectClass, baseClass}
              : new PsiClass[] {baseClass};
        }
        return new PsiClass[] {baseClass};
      }

      PsiClass objectClass =
          JavaPsiFacade.getInstance(psiClass.getProject())
              .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope());
      return objectClass != null ? new PsiClass[] {objectClass} : PsiClass.EMPTY_ARRAY;
    }
    if (psiClass instanceof PsiTypeParameter) {
      if (extendsListTypes.length == 0) {
        final PsiClass objectClass =
            JavaPsiFacade.getInstance(psiClass.getProject())
                .findClass(CommonClassNames.JAVA_LANG_OBJECT, psiClass.getResolveScope());
        return objectClass != null ? new PsiClass[] {objectClass} : PsiClass.EMPTY_ARRAY;
      }
      return resolveClassReferenceList(
          extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false);
    }

    PsiClass[] interfaces =
        resolveClassReferenceList(
            implementsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false);

    PsiClass superClass = getSuperClass(psiClass);
    if (superClass == null) return interfaces;
    PsiClass[] types = new PsiClass[interfaces.length + 1];
    types[0] = superClass;
    System.arraycopy(interfaces, 0, types, 1, interfaces.length);

    return types;
  }
  protected void performRefactoring(UsageInfo[] usages) {
    if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myTargetClass)) return;

    PsiMethod patternMethod = createMethodToAdd();
    final List<PsiReference> docRefs = new ArrayList<PsiReference>();
    for (UsageInfo usage : usages) {
      if (usage instanceof InheritorUsageInfo) {
        final PsiClass inheritor = ((InheritorUsageInfo) usage).getInheritor();
        addMethodToClass(inheritor, patternMethod, true);
      } else if (usage instanceof MethodCallUsageInfo
          && !((MethodCallUsageInfo) usage).isInternal()) {
        correctMethodCall(((MethodCallUsageInfo) usage).getMethodCallExpression(), false);
      } else if (usage instanceof JavadocUsageInfo) {
        docRefs.add(usage.getElement().getReference());
      }
    }

    try {
      if (myTargetClass.isInterface()) patternMethod.getBody().delete();

      final PsiMethod method = addMethodToClass(myTargetClass, patternMethod, false);
      myMethod.delete();
      for (PsiReference reference : docRefs) {
        reference.bindToElement(method);
      }
      VisibilityUtil.fixVisibility(usages, method, myNewVisibility);
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
  @NotNull
  public static PsiClassType[] getExtendsListTypes(GrTypeDefinition grType) {
    final PsiClassType[] extendsTypes = getReferenceListTypes(grType.getExtendsClause());
    if (grType.isInterface()) {
      return extendsTypes;
    }

    for (PsiClassType type : extendsTypes) {
      final PsiClass superClass = type.resolve();
      if (superClass instanceof GrTypeDefinition && !superClass.isInterface()
          || superClass != null
              && GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(
                  superClass.getQualifiedName())) {
        return extendsTypes;
      }
    }

    PsiClass grObSupport =
        GroovyPsiManager.getInstance(grType.getProject())
            .findClassWithCache(
                GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT, grType.getResolveScope());
    if (grObSupport != null) {
      final PsiClassType type =
          JavaPsiFacade.getInstance(grType.getProject())
              .getElementFactory()
              .createType(grObSupport);
      return ArrayUtil.append(extendsTypes, type, PsiClassType.ARRAY_FACTORY);
    }
    return extendsTypes;
  }
  /**
   * Adds all code methods of clazz add its super classes to signatures. Doesn't walk into
   * interfaces because all methods from them will be overloaded in any case. Besides Some of
   * interfaces came from delegates and they should be visited during the following processing.
   *
   * @param clazz current class
   * @param substitutor super class substitutor of clazz
   * @param signatures map to initialize
   * @param classes already visited classes
   */
  private static void initializeSignatures(
      PsiClass clazz,
      PsiSubstitutor substitutor,
      Map<MethodSignature, PsiMethod> signatures,
      Set<PsiClass> classes) {
    if (clazz.isInterface()) return;

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

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

      for (PsiClassType type : getSuperTypes(clazz)) {
        final PsiClassType.ClassResolveResult result = type.resolveGenerics();
        final PsiClass superClass = result.getElement();
        if (superClass == null) continue;
        final PsiSubstitutor superClassSubstitutor =
            TypeConversionUtil.getSuperClassSubstitutor(superClass, clazz, substitutor);
        initializeSignatures(superClass, superClassSubstitutor, signatures, classes);
      }
    }
  }
Exemplo n.º 7
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 void addInheritorUsages(
     PsiClass aClass, final GlobalSearchScope searchScope, final List<UsageInfo> usages) {
   for (PsiClass inheritor : ClassInheritorsSearch.search(aClass, searchScope, false).findAll()) {
     if (!inheritor.isInterface()) {
       usages.add(new InheritorUsageInfo(inheritor));
     } else {
       addInheritorUsages(inheritor, searchScope, usages);
     }
   }
 }
  protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
    final UsageInfo[] usages = refUsages.get();
    MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
    final Set<PsiMember> members = new HashSet<PsiMember>();
    members.add(myMethod);
    if (myTargetVariable instanceof PsiField) members.add((PsiMember) myTargetVariable);
    if (!myTargetClass.isInterface()) {
      RefactoringConflictsUtil.analyzeAccessibilityConflicts(
          members, myTargetClass, conflicts, myNewVisibility);
    } else {
      for (final UsageInfo usage : usages) {
        if (usage instanceof InheritorUsageInfo) {
          RefactoringConflictsUtil.analyzeAccessibilityConflicts(
              members, ((InheritorUsageInfo) usage).getInheritor(), conflicts, myNewVisibility);
        }
      }
    }

    if (myTargetVariable instanceof PsiParameter) {
      PsiParameter parameter = (PsiParameter) myTargetVariable;
      for (final UsageInfo usageInfo : usages) {
        if (usageInfo instanceof MethodCallUsageInfo) {
          final PsiElement methodCall = ((MethodCallUsageInfo) usageInfo).getMethodCallExpression();
          if (methodCall instanceof PsiMethodCallExpression) {
            final PsiExpression[] expressions =
                ((PsiMethodCallExpression) methodCall).getArgumentList().getExpressions();
            final int index = myMethod.getParameterList().getParameterIndex(parameter);
            if (index < expressions.length) {
              PsiExpression instanceValue = expressions[index];
              instanceValue = RefactoringUtil.unparenthesizeExpression(instanceValue);
              if (instanceValue instanceof PsiLiteralExpression
                  && ((PsiLiteralExpression) instanceValue).getValue() == null) {
                String message =
                    RefactoringBundle.message(
                        "0.contains.call.with.null.argument.for.parameter.1",
                        RefactoringUIUtil.getDescription(
                            ConflictsUtil.getContainer(methodCall), true),
                        CommonRefactoringUtil.htmlEmphasize(parameter.getName()));
                conflicts.putValue(instanceValue, message);
              }
            }
          } else if (methodCall instanceof PsiMethodReferenceExpression) {
            conflicts.putValue(methodCall, "Method reference would be broken after move");
          }
        }
      }
    }

    try {
      ConflictsUtil.checkMethodConflicts(myTargetClass, myMethod, getPatternMethod(), conflicts);
    } catch (IncorrectOperationException e) {
    }

    return showConflicts(conflicts, usages);
  }
  @NotNull
  public static PsiClass[] getInterfaces(@NotNull PsiClass psiClass) {
    if (psiClass.isInterface()) {
      final PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes();
      return resolveClassReferenceList(
          extendsListTypes, psiClass.getManager(), psiClass.getResolveScope(), false);
    }

    if (psiClass instanceof PsiAnonymousClass) {
      PsiClassType baseClassReference = ((PsiAnonymousClass) psiClass).getBaseClassType();
      PsiClass baseClass = baseClassReference.resolve();
      return baseClass != null && baseClass.isInterface()
          ? new PsiClass[] {baseClass}
          : PsiClass.EMPTY_ARRAY;
    }

    final PsiClassType[] implementsListTypes = psiClass.getImplementsListTypes();
    return resolveClassReferenceList(
        implementsListTypes, psiClass.getManager(), psiClass.getResolveScope(), 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;
 }
  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;
  }
Exemplo n.º 13
0
  public HaxePullUpHelper(PullUpData data) {
    myProject = data.getProject();
    myMembersToMove = data.getMembersToMove();
    myMembersAfterMove = data.getMovedMembers();
    myTargetSuperClass = data.getTargetClass();
    mySourceClass = data.getSourceClass();
    myJavaDocPolicy = data.getDocCommentPolicy();
    myIsTargetInterface = myTargetSuperClass.isInterface();

    myThisSuperAdjuster = new QualifiedThisSuperAdjuster();
    myExplicitSuperDeleter = new ExplicitSuperDeleter();
  }
 private static void generateDelegate(JavaChangeInfo changeInfo)
     throws IncorrectOperationException {
   final PsiMethod delegate = (PsiMethod) changeInfo.getMethod().copy();
   final PsiClass targetClass = changeInfo.getMethod().getContainingClass();
   LOG.assertTrue(!targetClass.isInterface());
   PsiElementFactory factory = JavaPsiFacade.getElementFactory(targetClass.getProject());
   ChangeSignatureProcessor.makeEmptyBody(factory, delegate);
   final PsiCallExpression callExpression =
       ChangeSignatureProcessor.addDelegatingCallTemplate(delegate, changeInfo.getNewName());
   addDelegateArguments(changeInfo, factory, callExpression);
   targetClass.addBefore(delegate, changeInfo.getMethod());
 }
  @NotNull
  protected UsageInfo[] findUsages() {
    final PsiManager manager = myMethod.getManager();
    final GlobalSearchScope searchScope = GlobalSearchScope.allScope(manager.getProject());
    final List<UsageInfo> usages = new ArrayList<UsageInfo>();
    for (PsiReference ref : ReferencesSearch.search(myMethod, searchScope, false)) {
      final PsiElement element = ref.getElement();
      if (element instanceof PsiReferenceExpression) {
        boolean isInternal = PsiTreeUtil.isAncestor(myMethod, element, true);
        usages.add(new MethodCallUsageInfo((PsiReferenceExpression) element, isInternal));
      } else if (element instanceof PsiDocTagValue) {
        usages.add(new JavadocUsageInfo(((PsiDocTagValue) element)));
      } else {
        throw new UnknownReferenceTypeException(element.getLanguage());
      }
    }

    if (myTargetClass.isInterface()) {
      addInheritorUsages(myTargetClass, searchScope, usages);
    }

    final PsiCodeBlock body = myMethod.getBody();
    if (body != null) {
      body.accept(
          new JavaRecursiveElementWalkingVisitor() {
            @Override
            public void visitNewExpression(PsiNewExpression expression) {
              if (MoveInstanceMembersUtil.getClassReferencedByThis(expression) != null) {
                usages.add(new InternalUsageInfo(expression));
              }
              super.visitNewExpression(expression);
            }

            @Override
            public void visitReferenceExpression(PsiReferenceExpression expression) {
              if (MoveInstanceMembersUtil.getClassReferencedByThis(expression) != null) {
                usages.add(new InternalUsageInfo(expression));
              } else if (!expression.isQualified()) {
                final PsiElement resolved = expression.resolve();
                if (myTargetVariable.equals(resolved)) {
                  usages.add(new InternalUsageInfo(expression));
                }
              }

              super.visitReferenceExpression(expression);
            }
          });
    }

    return usages.toArray(new UsageInfo[usages.size()]);
  }
  private PsiMethod getPatternMethod() throws IncorrectOperationException {
    final PsiMethod methodCopy = (PsiMethod) myMethod.copy();
    String name =
        myTargetClass.isInterface()
            ? PsiModifier.PUBLIC
            : !Comparing.strEqual(myNewVisibility, VisibilityUtil.ESCALATE_VISIBILITY)
                ? myNewVisibility
                : null;
    if (name != null) {
      PsiUtil.setModifierProperty(methodCopy, name, true);
    }
    if (myTargetVariable instanceof PsiParameter) {
      final int index =
          myMethod.getParameterList().getParameterIndex((PsiParameter) myTargetVariable);
      methodCopy.getParameterList().getParameters()[index].delete();
    }

    addParameters(
        JavaPsiFacade.getInstance(myProject).getElementFactory(),
        methodCopy,
        myTargetClass.isInterface());
    return methodCopy;
  }
 @NotNull
 public static PsiClass[] getInterfaces(@NotNull PsiTypeParameter typeParameter) {
   final PsiClassType[] referencedTypes = typeParameter.getExtendsListTypes();
   if (referencedTypes.length == 0) {
     return PsiClass.EMPTY_ARRAY;
   }
   final List<PsiClass> result = new ArrayList<PsiClass>(referencedTypes.length);
   for (PsiClassType referencedType : referencedTypes) {
     final PsiClass psiClass = referencedType.resolve();
     if (psiClass != null && psiClass.isInterface()) {
       result.add(psiClass);
     }
   }
   return result.toArray(new PsiClass[result.size()]);
 }
  private List<PsiClass> calculateInterfacesSupported() {
    final List<PsiClass> out = new ArrayList<PsiClass>();
    final PsiClass[] supers = sourceClass.getSupers();
    for (PsiClass superClass : supers) {
      if (!superClass.isInterface()) {
        continue;
      }
      final PsiMethod[] superclassMethods = superClass.getMethods();
      if (superclassMethods.length == 0) {
        continue;
      }
      boolean allMethodsCovered = true;

      for (PsiMethod method : superclassMethods) {
        boolean isCovered = false;
        for (PsiMethod movedMethod : methods) {
          if (isSuperMethod(method, movedMethod)) {
            isCovered = true;
            break;
          }
        }
        if (!isCovered) {
          allMethodsCovered = false;
          break;
        }
      }
      if (allMethodsCovered) {
        out.add(superClass);
      }
    }
    final Project project = sourceClass.getProject();
    final PsiManager manager = sourceClass.getManager();
    final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
    if (usesDefaultSerialization(sourceClass)) {
      final PsiClass serializable =
          JavaPsiFacade.getInstance(manager.getProject()).findClass("java.io.Serializable", scope);
      out.add(serializable);
    }
    if (usesDefaultClone(sourceClass)) {
      final PsiClass cloneable =
          JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Cloneable", scope);
      out.add(cloneable);
    }
    return out;
  }
  protected void performRefactoring(UsageInfo[] usages) {
    if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myTargetClass)) return;

    PsiMethod patternMethod = createMethodToAdd();
    final List<PsiReference> docRefs = new ArrayList<PsiReference>();
    for (UsageInfo usage : usages) {
      if (usage instanceof InheritorUsageInfo) {
        final PsiClass inheritor = ((InheritorUsageInfo) usage).getInheritor();
        addMethodToClass(inheritor, patternMethod, true);
      } else if (usage instanceof MethodCallUsageInfo
          && !((MethodCallUsageInfo) usage).isInternal()) {
        final PsiElement expression = ((MethodCallUsageInfo) usage).getMethodCallExpression();
        if (expression instanceof PsiMethodCallExpression) {
          correctMethodCall((PsiMethodCallExpression) expression, false);
        } else if (expression instanceof PsiMethodReferenceExpression) {
          PsiExpression newQualifier =
              JavaPsiFacade.getInstance(myProject)
                  .getElementFactory()
                  .createExpressionFromText(myTargetVariable.getType().getCanonicalText(), null);
          ((PsiMethodReferenceExpression) expression).setQualifierExpression(newQualifier);
        }
      } else if (usage instanceof JavadocUsageInfo) {
        docRefs.add(usage.getElement().getReference());
      }
    }

    try {
      if (myTargetClass.isInterface()) patternMethod.getBody().delete();

      final PsiMethod method = addMethodToClass(myTargetClass, patternMethod, false);
      myMethod.delete();
      for (PsiReference reference : docRefs) {
        reference.bindToElement(method);
      }
      VisibilityUtil.fixVisibility(UsageViewUtil.toElements(usages), method, myNewVisibility);

      if (myOpenInEditor) {
        EditorHelper.openInEditor(method);
      }
    } catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }
Exemplo n.º 20
0
 public static boolean isValidQualifier4InterfaceStaticMethodCall(
     @NotNull PsiMethod method,
     @NotNull PsiReferenceExpression methodReferenceExpression,
     @Nullable PsiElement scope,
     @NotNull LanguageLevel languageLevel) {
   if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
     final PsiExpression qualifierExpression = methodReferenceExpression.getQualifierExpression();
     final PsiClass containingClass = method.getContainingClass();
     if (containingClass != null
         && containingClass.isInterface()
         && method.hasModifierProperty(PsiModifier.STATIC)) {
       return qualifierExpression == null
               && (scope instanceof PsiImportStaticStatement
                   || PsiTreeUtil.isAncestor(containingClass, methodReferenceExpression, true))
           || qualifierExpression instanceof PsiReferenceExpression
               && ((PsiReferenceExpression) qualifierExpression).resolve() == containingClass;
     }
   }
   return true;
 }
Exemplo n.º 21
0
  @Nullable
  static List<MethodSignature> findFunctionCandidates(PsiClass psiClass) {
    if (psiClass instanceof PsiAnonymousClass) {
      psiClass = PsiUtil.resolveClassInType(((PsiAnonymousClass) psiClass).getBaseClassType());
    }
    if (psiClass != null && psiClass.isInterface()) {
      final List<MethodSignature> methods = new ArrayList<MethodSignature>();
      final Collection<HierarchicalMethodSignature> visibleSignatures =
          psiClass.getVisibleSignatures();
      for (HierarchicalMethodSignature signature : visibleSignatures) {
        final PsiMethod psiMethod = signature.getMethod();
        if (!psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) continue;
        if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) continue;
        if (!overridesPublicObjectMethod(psiMethod)) {
          methods.add(signature);
        }
      }

      return hasSubsignature(methods);
    }
    return null;
  }
  @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;
  }
Exemplo n.º 23
0
  @NotNull
  public Class classToClass(@NotNull PsiClass psiClass) {
    Set<String> modifiers = modifiersListToModifiersSet(psiClass.getModifierList());
    List<Field> fields = fieldsToFieldList(psiClass.getFields(), psiClass);
    List<Element> typeParameters = elementsToElementList(psiClass.getTypeParameters());
    List<Type> implementsTypes = typesToNotNullableTypeList(psiClass.getImplementsListTypes());
    List<Type> extendsTypes = typesToNotNullableTypeList(psiClass.getExtendsListTypes());
    IdentifierImpl name = new IdentifierImpl(psiClass.getName());
    List<Expression> baseClassParams = new LinkedList<Expression>();

    List<Member> members = getMembers(psiClass);

    // we try to find super() call and generate class declaration like that: class A(name: String, i
    // : Int) : Base(name)
    SuperVisitor visitor = new SuperVisitor();
    psiClass.accept(visitor);
    Collection<PsiExpressionList> resolvedSuperCallParameters =
        visitor.getResolvedSuperCallParameters();
    if (resolvedSuperCallParameters.size() == 1) {
      baseClassParams.addAll(
          expressionsToExpressionList(
              resolvedSuperCallParameters.toArray(new PsiExpressionList[1])[0].getExpressions()));
    }

    // we create primary constructor from all non final fields and fields without initializers
    if (!psiClass.isEnum()
        && !psiClass.isInterface()
        && psiClass.getConstructors().length > 1
        && getPrimaryConstructorForThisCase(psiClass) == null) {
      List<Field> finalOrWithEmptyInitializer = getFinalOrWithEmptyInitializer(fields);
      Map<String, String> initializers = new HashMap<String, String>();

      for (Member m : members) {
        // and modify secondaries
        if (m.getKind() == INode.Kind.CONSTRUCTOR) {
          Function f = (Function) m;
          if (!((Constructor) f).isPrimary()) {
            for (Field fo : finalOrWithEmptyInitializer) {
              String init = getDefaultInitializer(fo);
              initializers.put(fo.getIdentifier().toKotlin(), init);
            }

            List<Statement> newStatements = new LinkedList<Statement>();

            for (Statement s : f.getBlock().getStatements()) {
              boolean isRemoved = false;

              if (s.getKind() == INode.Kind.ASSIGNMENT_EXPRESSION) {
                AssignmentExpression assignmentExpression = (AssignmentExpression) s;
                if (assignmentExpression.getLeft().getKind() == INode.Kind.CALL_CHAIN) {
                  for (Field fo : finalOrWithEmptyInitializer) {
                    String id = fo.getIdentifier().toKotlin();
                    if (((CallChainExpression) assignmentExpression.getLeft())
                        .getIdentifier()
                        .toKotlin()
                        .endsWith("." + id)) {
                      initializers.put(id, assignmentExpression.getRight().toKotlin());
                      isRemoved = true;
                    }
                  }
                }
              }
              if (!isRemoved) {
                newStatements.add(s);
              }
            }

            newStatements.add(
                0,
                new DummyStringExpression(
                    "val __ = "
                        + createPrimaryConstructorInvocation(
                            name.toKotlin(), finalOrWithEmptyInitializer, initializers)));

            f.setBlock(new Block(newStatements));
          }
        }
      }

      members.add(
          new Constructor(
              Identifier.EMPTY_IDENTIFIER,
              Collections.<String>emptySet(),
              new ClassType(name),
              Collections.<Element>emptyList(),
              new ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)),
              new Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)),
              true));
    }

    if (psiClass.isInterface()) {
      return new Trait(
          this,
          name,
          modifiers,
          typeParameters,
          extendsTypes,
          Collections.<Expression>emptyList(),
          implementsTypes,
          members);
    }
    if (psiClass.isEnum()) {
      return new Enum(
          this,
          name,
          modifiers,
          typeParameters,
          Collections.<Type>emptyList(),
          Collections.<Expression>emptyList(),
          implementsTypes,
          members);
    }
    return new Class(
        this,
        name,
        modifiers,
        typeParameters,
        extendsTypes,
        baseClassParams,
        implementsTypes,
        members);
  }
  @Override
  public void processElementUsages(
      @NotNull final PsiElement element,
      @NotNull final Processor<UsageInfo> processor,
      @NotNull final FindUsagesOptions options) {
    if (options instanceof JavaVariableFindUsagesOptions) {
      final JavaVariableFindUsagesOptions varOptions = (JavaVariableFindUsagesOptions) options;
      if (varOptions.isReadAccess || varOptions.isWriteAccess) {
        if (varOptions.isReadAccess && varOptions.isWriteAccess) {
          addElementUsages(element, processor, options);
        } else {
          addElementUsages(
              element,
              new Processor<UsageInfo>() {
                @Override
                public boolean process(UsageInfo info) {
                  final PsiElement element = info.getElement();
                  boolean isWrite =
                      element instanceof PsiExpression
                          && PsiUtil.isAccessedForWriting((PsiExpression) element);
                  if (isWrite == varOptions.isWriteAccess) {
                    if (!processor.process(info)) return false;
                  }
                  return true;
                }
              },
              varOptions);
        }
      }
    } else if (options.isUsages) {
      addElementUsages(element, processor, options);
    }

    ApplicationManager.getApplication()
        .runReadAction(
            new Runnable() {
              @Override
              public void run() {
                if (ThrowSearchUtil.isSearchable(element)
                    && options instanceof JavaThrowFindUsagesOptions
                    && options.isUsages) {
                  ThrowSearchUtil.Root root =
                      options.getUserData(ThrowSearchUtil.THROW_SEARCH_ROOT_KEY);
                  if (root == null) {
                    final ThrowSearchUtil.Root[] roots = ThrowSearchUtil.getSearchRoots(element);
                    if (roots != null && roots.length > 0) {
                      root = roots[0];
                    }
                  }
                  if (root != null) {
                    ThrowSearchUtil.addThrowUsages(processor, root, options);
                  }
                }
              }
            });

    if (options instanceof JavaPackageFindUsagesOptions
        && ((JavaPackageFindUsagesOptions) options).isClassesUsages) {
      addClassesUsages((PsiPackage) element, processor, (JavaPackageFindUsagesOptions) options);
    }

    if (options instanceof JavaClassFindUsagesOptions) {
      final JavaClassFindUsagesOptions classOptions = (JavaClassFindUsagesOptions) options;
      final PsiClass psiClass = (PsiClass) element;
      if (classOptions.isMethodsUsages) {
        addMethodsUsages(psiClass, processor, classOptions);
      }
      if (classOptions.isFieldsUsages) {
        addFieldsUsages(psiClass, processor, classOptions);
      }
      if (psiClass.isInterface()) {
        if (classOptions.isDerivedInterfaces) {
          if (classOptions.isImplementingClasses) {
            addInheritors(psiClass, processor, classOptions);
          } else {
            addDerivedInterfaces(psiClass, processor, classOptions);
          }
        } else if (classOptions.isImplementingClasses) {
          addImplementingClasses(psiClass, processor, classOptions);
        }
      } else if (classOptions.isDerivedClasses) {
        addInheritors(psiClass, processor, classOptions);
      }
    }

    if (options instanceof JavaMethodFindUsagesOptions) {
      final PsiMethod psiMethod = (PsiMethod) element;
      boolean isAbstract =
          ApplicationManager.getApplication()
              .runReadAction(
                  new Computable<Boolean>() {
                    @Override
                    public Boolean compute() {
                      return psiMethod.hasModifierProperty(PsiModifier.ABSTRACT);
                    }
                  });
      final JavaMethodFindUsagesOptions methodOptions = (JavaMethodFindUsagesOptions) options;
      if (isAbstract && methodOptions.isImplementingMethods || methodOptions.isOverridingMethods) {
        processOverridingMethods(psiMethod, processor, methodOptions);
      }
    }

    if (element instanceof PomTarget) {
      addAliasingUsages((PomTarget) element, processor, options);
    }
    final Boolean isSearchable =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<Boolean>() {
                  @Override
                  public Boolean compute() {
                    return ThrowSearchUtil.isSearchable(element);
                  }
                });
    if (!isSearchable
        && options.isSearchForTextOccurrences
        && options.searchScope instanceof GlobalSearchScope) {
      // todo add to fastTrack
      processUsagesInText(element, processor, (GlobalSearchScope) options.searchScope);
    }
  }
  // returns super method, sub class
  public static Pair<PsiMethod, PsiClass> getSiblingInheritedViaSubClass(
      @NotNull final PsiMethod method, @NotNull Map<PsiClass, PsiClass> subClassCache) {
    if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return null;
    if (method.hasModifierProperty(PsiModifier.STATIC)) return null;
    final PsiClass containingClass = method.getContainingClass();
    boolean hasSubClass =
        containingClass != null
            && !containingClass.isInterface()
            && subClassCache.get(containingClass) != null;
    if (!hasSubClass) {
      return null;
    }
    final Collection<PsiAnchor> checkedInterfaces = new THashSet<PsiAnchor>();
    final Ref<Pair<PsiMethod, PsiClass>> result = Ref.create();
    ClassInheritorsSearch.search(containingClass, containingClass.getUseScope(), true, true, false)
        .forEach(
            new Processor<PsiClass>() {
              @Override
              public boolean process(PsiClass inheritor) {
                for (PsiClassType interfaceType : inheritor.getImplementsListTypes()) {
                  PsiClassType.ClassResolveResult resolved = interfaceType.resolveGenerics();
                  PsiClass anInterface = resolved.getElement();
                  if (anInterface == null || !checkedInterfaces.add(PsiAnchor.create(anInterface)))
                    continue;
                  for (PsiMethod superMethod :
                      anInterface.findMethodsByName(method.getName(), true)) {
                    PsiClass superInterface = superMethod.getContainingClass();
                    if (superInterface == null) {
                      continue;
                    }
                    if (containingClass.isInheritor(superInterface, true)) {
                      // if containingClass implements the superInterface then it's not a sibling
                      // inheritance but a pretty boring the usual one
                      continue;
                    }

                    // calculate substitutor of containingClass --> inheritor
                    PsiSubstitutor substitutor =
                        TypeConversionUtil.getSuperClassSubstitutor(
                            containingClass, inheritor, PsiSubstitutor.EMPTY);
                    // calculate substitutor of inheritor --> superInterface
                    substitutor =
                        TypeConversionUtil.getSuperClassSubstitutor(
                            superInterface, inheritor, substitutor);

                    final MethodSignature superSignature = superMethod.getSignature(substitutor);
                    final MethodSignature derivedSignature =
                        method.getSignature(PsiSubstitutor.EMPTY);
                    boolean isOverridden =
                        MethodSignatureUtil.isSubsignature(superSignature, derivedSignature);

                    if (!isOverridden) {
                      continue;
                    }
                    result.set(Pair.create(superMethod, inheritor));
                    return false;
                  }
                }
                return true;
              }
            });
    return result.get();
  }