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;
  }
  /**
   * Creates a new {@link ClassElement} object.
   *
   * @param clazz class information.
   * @return a new {@link ClassElement} object.
   */
  public static ClassElement newClassElement(PsiClass clazz) {
    ClassElement ce = new ClassElement();

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

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

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

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

    return ce;
  }
  private static boolean containsAllCases(GrSwitchStatement statement) {
    final GrCaseSection[] sections = statement.getCaseSections();
    for (GrCaseSection section : sections) {
      if (section.isDefault()) return true;
    }

    final GrExpression condition = statement.getCondition();
    if (!(condition instanceof GrReferenceExpression)) return false;

    PsiType type = TypesUtil.unboxPrimitiveTypeWrapper(getNominalTypeNoRecursion(condition));
    if (type == null) return false;

    if (type instanceof PsiPrimitiveType) {
      if (type == PsiType.BOOLEAN) return sections.length == 2;
      if (type == PsiType.BYTE || type == PsiType.CHAR) return sections.length == 128;
      return false;
    }

    if (type instanceof PsiClassType) {
      final PsiClass resolved = ((PsiClassType) type).resolve();
      if (resolved != null && resolved.isEnum()) {
        int enumConstantCount = 0;
        final PsiField[] fields = resolved.getFields();
        for (PsiField field : fields) {
          if (field instanceof PsiEnumConstant) enumConstantCount++;
        }

        if (sections.length == enumConstantCount) return true;
      }
    }

    return false;
  }
 @Override
 public void visitMethod(@NotNull PsiMethod method) {
   // don't call super, to keep this from drilling in
   if (!method.isConstructor()) {
     return;
   }
   if (!method.hasModifierProperty(PsiModifier.PRIVATE)) {
     return;
   }
   final PsiClass aClass = method.getContainingClass();
   if (aClass == null) {
     return;
   }
   if (!aClass.isEnum()) {
     return;
   }
   final PsiModifierList modifiers = method.getModifierList();
   final PsiElement[] children = modifiers.getChildren();
   for (final PsiElement child : children) {
     final String text = child.getText();
     if (PsiModifier.PRIVATE.equals(text)) {
       registerError(child, child, method);
     }
   }
 }
 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();
 }
  @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;
  }
 @Override
 public boolean accepts(
     @NotNull PsiSwitchStatement psiSwitchStatement,
     ProcessingContext context) {
   final PsiExpression expression =
       psiSwitchStatement.getExpression();
   if (expression == null) return false;
   PsiClass aClass =
       PsiUtil.resolveClassInClassTypeOnly(expression.getType());
   return aClass != null && aClass.isEnum();
 }
 public void testEnumWithConstants() throws Exception {
   setupLoadingFilter();
   PsiClass enumClass =
       myJavaFacade.findClass(
           "enums.OurEnumWithConstants", GlobalSearchScope.moduleScope(myModule));
   assertNotNull(enumClass);
   assertTrue(enumClass.isEnum());
   checkEnumWithConstants(enumClass, false);
   teardownLoadingFilter();
   checkEnumWithConstants(enumClass, true);
 }
 @Override
 @NotNull
 public PsiClass createEnum(@NotNull PsiDirectory dir, @NotNull String name)
     throws IncorrectOperationException {
   String templateName = JavaTemplateUtil.INTERNAL_ENUM_TEMPLATE_NAME;
   PsiClass someClass = createClassFromTemplate(dir, name, templateName);
   if (!someClass.isEnum()) {
     throw new IncorrectOperationException(getIncorrectTemplateMessage(templateName));
   }
   return someClass;
 }
 @Override
 public void visitClass(PsiClass aClass) {
   ArrangementSettingsToken type = CLASS;
   if (aClass.isEnum()) {
     type = ENUM;
   } else if (aClass.isInterface()) {
     type = INTERFACE;
   }
   JavaElementArrangementEntry entry =
       createNewEntry(aClass, aClass.getTextRange(), type, aClass.getName(), true);
   processEntry(entry, aClass, aClass);
 }
    @Override
    public Boolean visitClassType(PsiClassType classType) {
      if (classType.getParameters().length > 0) {
        PsiClassType rawType = classType.rawType();
        return rawType.equalsToText(CommonClassNames.JAVA_LANG_CLASS);
      }

      PsiClass aClass = classType.resolve();
      if (aClass != null && (aClass.isAnnotationType() || aClass.isEnum())) {
        return Boolean.TRUE;
      }

      return classType.equalsToText(CommonClassNames.JAVA_LANG_CLASS)
          || classType.equalsToText(CommonClassNames.JAVA_LANG_STRING);
    }
  public static boolean hasAccessibleConstructor(PsiType type) {
    if (type instanceof PsiArrayType) return true;

    final PsiClass psiClass = PsiUtil.resolveClassInType(type);
    if (psiClass == null || psiClass.isEnum() || psiClass.isAnnotationType()) return false;

    if (!(psiClass instanceof PsiCompiledElement)) return true;

    final PsiMethod[] methods = psiClass.getConstructors();
    if (methods.length == 0) return true;

    for (final PsiMethod method : methods) {
      if (!method.hasModifierProperty(PsiModifier.PRIVATE)) return true;
    }
    return false;
  }
 public boolean satisfiedBy(PsiElement element) {
   if (!(element instanceof PsiSwitchStatement)) {
     return false;
   }
   final PsiSwitchStatement switchStatement = (PsiSwitchStatement) element;
   final PsiCodeBlock body = switchStatement.getBody();
   if (body == null) {
     return false;
   }
   final PsiExpression expression = switchStatement.getExpression();
   if (expression == null) {
     return false;
   }
   final PsiType type = expression.getType();
   if (!(type instanceof PsiClassType)) {
     return false;
   }
   final PsiClass enumClass = ((PsiClassType) type).resolve();
   if (enumClass == null || !enumClass.isEnum()) {
     return false;
   }
   final PsiField[] fields = enumClass.getFields();
   final Set<String> enumElements = new HashSet<String>(fields.length);
   for (final PsiField field : fields) {
     final PsiType fieldType = field.getType();
     if (fieldType.equals(type)) {
       final String fieldName = field.getName();
       enumElements.add(fieldName);
     }
   }
   final PsiStatement[] statements = body.getStatements();
   for (PsiStatement statement : statements) {
     if (statement instanceof PsiSwitchLabelStatement) {
       final PsiSwitchLabelStatement labelStatement = (PsiSwitchLabelStatement) statement;
       final PsiExpression value = labelStatement.getCaseValue();
       if (value != null) {
         final String valueText = value.getText();
         enumElements.remove(valueText);
       }
     }
   }
   if (enumElements.isEmpty()) {
     return false;
   }
   return !ErrorUtil.containsError(element);
 }
Beispiel #14
0
 private static String getContainingClassDescription(PsiClass aClass, String formatted) {
   if (aClass instanceof PsiAnonymousClass) {
     return LangBundle.message("java.terms.of.anonymous.class", formatted);
   } else {
     final String qualifiedName = aClass.getQualifiedName();
     final String className = qualifiedName != null ? qualifiedName : aClass.getName();
     if (aClass.isInterface()) {
       return LangBundle.message("java.terms.of.interface", formatted, className);
     }
     if (aClass.isEnum()) {
       return LangBundle.message("java.terms.of.enum", formatted, className);
     }
     if (aClass.isAnnotationType()) {
       return LangBundle.message("java.terms.of.annotation.type", formatted, className);
     }
     return LangBundle.message("java.terms.of.class", formatted, className);
   }
 }
 @NotNull
 public static PsiClassType[] getExtendsListTypes(@NotNull PsiClass psiClass) {
   if (psiClass.isEnum()) {
     PsiClassType enumSuperType =
         getEnumSuperType(
             psiClass, JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory());
     return enumSuperType == null ? PsiClassType.EMPTY_ARRAY : new PsiClassType[] {enumSuperType};
   }
   if (psiClass.isAnnotationType()) {
     return new PsiClassType[] {
       getAnnotationSuperType(
           psiClass, JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory())
     };
   }
   final PsiReferenceList extendsList = psiClass.getExtendsList();
   if (extendsList != null) {
     return extendsList.getReferencedTypes();
   }
   return PsiClassType.EMPTY_ARRAY;
 }
  @Override
  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
    int offset = editor.getCaretModel().getOffset();
    final PsiMethod method = findMethod(file, offset);

    if (method == null || !method.isValid()) return false;
    setText(getIntentionName(method));

    if (!method.getManager().isInProject(method)) return false;

    PsiClass containingClass = method.getContainingClass();
    if (containingClass == null) return false;
    final boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
    if (isAbstract
        || !method.hasModifierProperty(PsiModifier.PRIVATE)
            && !method.hasModifierProperty(PsiModifier.STATIC)) {
      if (!isAbstract && !isOnIdentifier(file, offset)) return false;
      MyElementProcessor processor = new MyElementProcessor(method);
      if (containingClass.isEnum()) {
        for (PsiField field : containingClass.getFields()) {
          if (field instanceof PsiEnumConstant) {
            final PsiEnumConstantInitializer initializingClass =
                ((PsiEnumConstant) field).getInitializingClass();
            if (initializingClass == null) {
              processor.myHasMissingImplementations = true;
            } else {
              if (!processor.execute(initializingClass)) {
                break;
              }
            }
          }
        }
      }
      ClassInheritorsSearch.search(containingClass, false)
          .forEach(new PsiElementProcessorAdapter<PsiClass>(processor));
      return isAvailable(processor);
    }

    return false;
  }
 @Override
 public void visitClass(@NotNull PsiClass aClass) {
   if (!aClass.isEnum()) {
     return;
   }
   if (!ClassUtils.isInnerClass(aClass)) {
     return;
   }
   if (!aClass.hasModifierProperty(PsiModifier.STATIC)) {
     return;
   }
   final PsiModifierList modifiers = aClass.getModifierList();
   if (modifiers == null) {
     return;
   }
   final PsiElement[] children = modifiers.getChildren();
   for (final PsiElement child : children) {
     final String text = child.getText();
     if (PsiModifier.STATIC.equals(text)) {
       registerError(child, child, aClass);
     }
   }
 }
    private void checkExpression(PsiExpression expression) {
      if (expression == null) return;

      final PsiType type = expression.getType();
      if (!(type instanceof PsiClassType)) return;

      if (IGNORE_TOSTRING
          && MethodUtils.isToString(PsiTreeUtil.getParentOfType(expression, PsiMethod.class)))
        return;

      if (IGNORE_EXCEPTION
          && (ExceptionUtils.isExceptionArgument(expression)
              || PsiTreeUtil.getParentOfType(
                      expression, PsiThrowStatement.class, true, PsiCodeBlock.class, PsiClass.class)
                  != null)) return;

      if (IGNORE_ASSERT
          && PsiTreeUtil.getParentOfType(
                  expression, PsiAssertStatement.class, true, PsiCodeBlock.class, PsiClass.class)
              != null) {
        return;
      }

      if (IGNORE_NONNLS && NonNlsUtils.isNonNlsAnnotatedUse(expression)) return;

      final PsiClassType classType = (PsiClassType) type;
      if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return;

      final PsiClass referencedClass = classType.resolve();
      if (referencedClass == null || referencedClass instanceof PsiTypeParameter) return;
      if (referencedClass.isEnum() || referencedClass.isInterface()) return;
      if (referencedClass.hasModifierProperty(PsiModifier.ABSTRACT)
          && !(expression instanceof PsiSuperExpression)) return;
      if (hasGoodToString(referencedClass)) return;

      registerError(expression);
    }
  private static String generateClassInfo(PsiClass aClass) {
    StringBuilder buffer = new StringBuilder();
    GroovyFile file = (GroovyFile) aClass.getContainingFile();

    String packageName = file.getPackageName();
    if (!packageName.isEmpty()) {
      buffer.append(packageName).append("\n");
    }

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

    JavaDocumentationProvider.generateTypeParameters(aClass, buffer);

    JavaDocumentationProvider.writeExtends(aClass, buffer, aClass.getExtendsListTypes());
    JavaDocumentationProvider.writeImplements(aClass, buffer, aClass.getImplementsListTypes());

    return buffer.toString();
  }
  private PsiClass buildClass() {
    final PsiManager manager = sourceClass.getManager();
    final Project project = sourceClass.getProject();
    final ExtractedClassBuilder extractedClassBuilder = new ExtractedClassBuilder();
    extractedClassBuilder.setProject(myProject);
    extractedClassBuilder.setClassName(newClassName);
    extractedClassBuilder.setPackageName(newPackageName);
    extractedClassBuilder.setOriginalClassName(sourceClass.getQualifiedName());
    extractedClassBuilder.setRequiresBackPointer(requiresBackpointer);
    extractedClassBuilder.setExtractAsEnum(enumConstants);
    for (PsiField field : fields) {
      extractedClassBuilder.addField(field);
    }
    for (PsiMethod method : methods) {
      extractedClassBuilder.addMethod(method);
    }
    for (PsiClass innerClass : innerClasses) {
      extractedClassBuilder.addInnerClass(
          innerClass, innerClassesToMakePublic.contains(innerClass));
    }
    extractedClassBuilder.setTypeArguments(typeParams);
    final List<PsiClass> interfaces = calculateInterfacesSupported();
    extractedClassBuilder.setInterfaces(interfaces);

    if (myGenerateAccessors) {
      final NecessaryAccessorsVisitor visitor = checkNecessaryGettersSetters4ExtractedClass();
      sourceClass.accept(visitor);
      extractedClassBuilder.setFieldsNeedingGetters(visitor.getFieldsNeedingGetter());
      extractedClassBuilder.setFieldsNeedingSetters(visitor.getFieldsNeedingSetter());
    }

    final String classString = extractedClassBuilder.buildBeanClass();
    if (extractInnerClass) {
      final PsiFileFactory factory = PsiFileFactory.getInstance(project);
      final PsiJavaFile newFile =
          (PsiJavaFile)
              factory.createFileFromText(
                  newClassName + ".java", JavaFileType.INSTANCE, classString);
      final PsiClass psiClass = newFile.getClasses()[0];
      if (!psiClass.isEnum()) {
        final PsiModifierList modifierList = psiClass.getModifierList();
        assert modifierList != null;
        modifierList.setModifierProperty(PsiModifier.STATIC, true);
      }
      final PsiElement addedClass = sourceClass.add(psiClass);
      return (PsiClass)
          CodeStyleManager.getInstance(manager)
              .reformat(
                  JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedClass));
    }

    try {
      final PsiFile containingFile = sourceClass.getContainingFile();
      final PsiDirectory directory;
      final PsiDirectory containingDirectory = containingFile.getContainingDirectory();
      if (myMoveDestination != null) {
        directory = myMoveDestination.getTargetDirectory(containingDirectory);
      } else {
        final Module module = ModuleUtil.findModuleForPsiElement(containingFile);
        assert module != null;
        directory =
            PackageUtil.findOrCreateDirectoryForPackage(
                module, newPackageName, containingDirectory, false, true);
      }
      if (directory != null) {
        final PsiFileFactory factory = PsiFileFactory.getInstance(project);
        final PsiFile newFile =
            factory.createFileFromText(newClassName + ".java", JavaFileType.INSTANCE, classString);
        final PsiElement addedFile = directory.add(newFile);
        final CodeStyleManager codeStyleManager =
            CodeStyleManager.getInstance(manager.getProject());
        final PsiElement shortenedFile =
            JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedFile);
        return ((PsiJavaFile) codeStyleManager.reformat(shortenedFile)).getClasses()[0];
      } else {
        return null;
      }
    } catch (IncorrectOperationException e) {
      return null;
    }
  }
  @SuppressWarnings({"HardCodedStringLiteral"})
  private static String generateClassInfo(PsiClass aClass) {
    StringBuilder buffer = new StringBuilder();
    GroovyFile file = (GroovyFile) aClass.getContainingFile();

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

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

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

      buffer.append("<");

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

        PsiTypeParameter tp = typeParameters[i];

        buffer.append(tp.getName());

        PsiClassType[] refs = tp.getExtendsListTypes();

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

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

      buffer.append(">");
    }

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

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

    return buffer.toString();
  }
    private void checkMember(@NotNull final PsiMember member) {
      if (member.hasModifierProperty(PsiModifier.PRIVATE)
          || member.hasModifierProperty(PsiModifier.NATIVE)) return;
      if (member instanceof PsiMethod && member instanceof SyntheticElement || !member.isPhysical())
        return;

      if (member instanceof PsiMethod) {
        PsiMethod method = (PsiMethod) member;
        if (!method.getHierarchicalMethodSignature().getSuperSignatures().isEmpty()) {
          log(member.getName() + " overrides");
          return; // overrides
        }
        if (MethodUtils.isOverridden(method)) {
          log(member.getName() + " overridden");
          return;
        }
      }
      if (member instanceof PsiEnumConstant) return;
      if (member instanceof PsiClass
          && (member instanceof PsiAnonymousClass
              || member instanceof PsiTypeParameter
              || member instanceof PsiSyntheticClass
              || PsiUtil.isLocalClass((PsiClass) member))) {
        return;
      }
      final PsiClass memberClass = member.getContainingClass();
      if (memberClass != null
          && (memberClass.isInterface()
              || memberClass.isEnum()
              || memberClass.isAnnotationType()
              || PsiUtil.isLocalClass(memberClass) && member instanceof PsiClass)) {
        return;
      }
      final PsiFile memberFile = member.getContainingFile();
      Project project = memberFile.getProject();

      if (myDeadCodeInspection.isEntryPoint(member)) {
        log(member.getName() + " is entry point");
        return;
      }

      PsiModifierList memberModifierList = member.getModifierList();
      if (memberModifierList == null) return;
      final int currentLevel = PsiUtil.getAccessLevel(memberModifierList);
      final AtomicInteger maxLevel = new AtomicInteger(PsiUtil.ACCESS_LEVEL_PRIVATE);
      final AtomicBoolean foundUsage = new AtomicBoolean();
      PsiDirectory memberDirectory = memberFile.getContainingDirectory();
      final PsiPackage memberPackage =
          memberDirectory == null
              ? null
              : JavaDirectoryService.getInstance().getPackage(memberDirectory);
      log(member.getName() + ": checking effective level for " + member);
      boolean result =
          UnusedSymbolUtil.processUsages(
              project,
              memberFile,
              member,
              new EmptyProgressIndicator(),
              null,
              new Processor<UsageInfo>() {
                @Override
                public boolean process(UsageInfo info) {
                  foundUsage.set(true);
                  PsiFile psiFile = info.getFile();
                  if (psiFile == null) return true;
                  if (!(psiFile instanceof PsiJavaFile)) {
                    log("     refd from " + psiFile.getName() + "; set to public");
                    maxLevel.set(PsiUtil.ACCESS_LEVEL_PUBLIC);
                    if (memberClass != null) {
                      childMembersAreUsedOutsideMyPackage.add(memberClass);
                    }
                    return false; // referenced from XML, has to be public
                  }
                  // int offset = info.getNavigationOffset();
                  // if (offset == -1) return true;
                  PsiElement element = info.getElement();
                  if (element == null) return true;
                  @PsiUtil.AccessLevel
                  int level =
                      getEffectiveLevel(element, psiFile, memberFile, memberClass, memberPackage);
                  log(
                      "    ref in file "
                          + psiFile.getName()
                          + "; level = "
                          + PsiUtil.getAccessModifier(level)
                          + "; ("
                          + element
                          + ")");
                  while (true) {
                    int oldLevel = maxLevel.get();
                    if (level <= oldLevel || maxLevel.compareAndSet(oldLevel, level)) break;
                  }
                  if (level == PsiUtil.ACCESS_LEVEL_PUBLIC && memberClass != null) {
                    childMembersAreUsedOutsideMyPackage.add(memberClass);
                  }

                  return level != PsiUtil.ACCESS_LEVEL_PUBLIC;
                }
              });

      if (!foundUsage.get()) {
        log(member.getName() + " unused; ignore");
        return; // do not propose private for unused method
      }
      int max = maxLevel.get();
      if (max == PsiUtil.ACCESS_LEVEL_PRIVATE && memberClass == null) {
        max = PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL;
      }

      log(member.getName() + ": effective level is '" + PsiUtil.getAccessModifier(max) + "'");

      if (max < currentLevel) {
        if (max == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL
            && member instanceof PsiClass
            && childMembersAreUsedOutsideMyPackage.contains(member)) {
          log(member.getName() + "  children used outside my package; ignore");
          return; // e.g. some public method is used outside my package (without importing class)
        }
        PsiElement toHighlight =
            currentLevel == PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL
                ? ((PsiNameIdentifierOwner) member).getNameIdentifier()
                : ContainerUtil.find(
                    memberModifierList.getChildren(),
                    new Condition<PsiElement>() {
                      @Override
                      public boolean value(PsiElement element) {
                        return element instanceof PsiKeyword
                            && element.getText().equals(PsiUtil.getAccessModifier(currentLevel));
                      }
                    });
        assert toHighlight != null
            : member
                + " ; "
                + ((PsiNameIdentifierOwner) member).getNameIdentifier()
                + "; "
                + memberModifierList.getText();
        myHolder.registerProblem(
            toHighlight,
            "Access can be " + PsiUtil.getAccessModifier(max),
            new ChangeModifierFix(PsiUtil.getAccessModifier(max)));
      }
    }
  public void invoke(
      @NotNull final Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
    if (elements.length != 1) return;

    myProject = project;
    mySubclass = (PsiClass) elements[0];

    if (!CommonRefactoringUtil.checkReadOnlyStatus(project, mySubclass)) return;

    Editor editor = dataContext != null ? PlatformDataKeys.EDITOR.getData(dataContext) : null;
    if (mySubclass.isInterface()) {
      String message =
          RefactoringBundle.getCannotRefactorMessage(
              RefactoringBundle.message("superclass.cannot.be.extracted.from.an.interface"));
      CommonRefactoringUtil.showErrorHint(
          project, editor, message, REFACTORING_NAME, HelpID.EXTRACT_SUPERCLASS);
      return;
    }

    if (mySubclass.isEnum()) {
      String message =
          RefactoringBundle.getCannotRefactorMessage(
              RefactoringBundle.message("superclass.cannot.be.extracted.from.an.enum"));
      CommonRefactoringUtil.showErrorHint(
          project, editor, message, REFACTORING_NAME, HelpID.EXTRACT_SUPERCLASS);
      return;
    }

    final List<MemberInfo> memberInfos =
        MemberInfo.extractClassMembers(
            mySubclass,
            new MemberInfo.Filter<PsiMember>() {
              public boolean includeMember(PsiMember element) {
                return true;
              }
            },
            false);

    final ExtractSuperclassDialog dialog =
        new ExtractSuperclassDialog(
            project, mySubclass, memberInfos, ExtractSuperclassHandler.this);
    dialog.show();
    if (!dialog.isOK() || !dialog.isExtractSuperclass()) return;

    CommandProcessor.getInstance()
        .executeCommand(
            myProject,
            new Runnable() {
              public void run() {
                final Runnable action =
                    new Runnable() {
                      public void run() {
                        doRefactoring(project, mySubclass, dialog);
                      }
                    };
                ApplicationManager.getApplication().runWriteAction(action);
              }
            },
            REFACTORING_NAME,
            null);
  }
  public void testEnumWithInitializedConstants() throws Exception {
    setupLoadingFilter();
    final GlobalSearchScope moduleScope = GlobalSearchScope.moduleScope(myModule);
    PsiClass enumClass =
        myJavaFacade.findClass("enums.OurEnumWithInitializedConstants", moduleScope);
    assertNotNull(enumClass);
    assertTrue(enumClass.isEnum());
    PsiField[] fields = enumClass.getFields();
    assertEquals(3, fields.length);
    assertTrue(fields[0] instanceof PsiEnumConstant);
    assertTrue(fields[1] instanceof PsiEnumConstant);
    assertTrue(fields[2] instanceof PsiEnumConstant);
    PsiAnonymousClass initializingClass0 = ((PsiEnumConstant) fields[0]).getInitializingClass();
    PsiClass baseClass0 = initializingClass0.getBaseClassType().resolve();
    assertTrue(baseClass0 == enumClass);

    PsiAnonymousClass initializingClass1 = ((PsiEnumConstant) fields[1]).getInitializingClass();
    PsiClass baseClass1 = initializingClass1.getBaseClassType().resolve();
    assertTrue(baseClass1 == enumClass);

    PsiAnonymousClass initializingClass2 = ((PsiEnumConstant) fields[1]).getInitializingClass();
    PsiClass baseClass2 = initializingClass2.getBaseClassType().resolve();
    assertTrue(baseClass2 == enumClass);

    assertTrue(initializingClass0.isInheritor(enumClass, false));
    assertTrue(initializingClass1.isInheritor(enumClass, false));
    assertTrue(initializingClass2.isInheritor(enumClass, false));

    final PsiClass[] enumInheritors =
        ClassInheritorsSearch.search(enumClass, moduleScope, false).toArray(PsiClass.EMPTY_ARRAY);
    assertEquals(3, enumInheritors.length);
    assertTrue(Arrays.asList(enumInheritors).contains(initializingClass0));
    assertTrue(Arrays.asList(enumInheritors).contains(initializingClass1));
    assertTrue(Arrays.asList(enumInheritors).contains(initializingClass2));

    PsiMethod[] methods1 = initializingClass2.getMethods();
    assertEquals(1, methods1.length);
    assertEquals("foo", methods1[0].getName());

    final PsiClass baseInterfaceClass =
        myJavaFacade.findClass(
            "enums.OurBaseInterface", GlobalSearchScope.moduleWithLibrariesScope(myModule));
    assertNotNull(baseInterfaceClass);

    final PsiClass[] inheritors =
        ClassInheritorsSearch.search(baseInterfaceClass, moduleScope, false)
            .toArray(PsiClass.EMPTY_ARRAY);
    assertEquals(1, inheritors.length);
    assertTrue(inheritors[0] instanceof PsiAnonymousClass);

    teardownLoadingFilter();

    assertTrue(inheritors[0].getParent().getParent() instanceof PsiExpressionList);
    assertTrue(inheritors[0].getParent().getParent().getParent() == fields[2]);

    final PsiExpression[] expressions2 =
        ((PsiEnumConstant) fields[2]).getArgumentList().getExpressions();
    assertEquals(1, expressions2.length);
    assertTrue(expressions2[0] instanceof PsiNewExpression);
    final PsiAnonymousClass anonymousClass2 =
        ((PsiNewExpression) expressions2[0]).getAnonymousClass();
    assertTrue(anonymousClass2 != null);
    assertTrue(anonymousClass2.isInheritor(baseInterfaceClass, false));
  }
Beispiel #25
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);
  }