All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.siyeh.ig.packaging.DisjointPackageInspection Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition java-analysis-impl library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2006-2011 Dave Griffith, Bas Leijdekkers
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.siyeh.ig.packaging;

import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInspection.CommonProblemDescriptor;
import com.intellij.codeInspection.GlobalInspectionContext;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.reference.RefClass;
import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.codeInspection.reference.RefJavaUtil;
import com.intellij.codeInspection.reference.RefPackage;
import com.intellij.psi.PsiClass;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseGlobalInspection;
import com.siyeh.ig.dependency.DependencyUtils;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class DisjointPackageInspection extends BaseGlobalInspection {

  @NotNull
  @Override
  public String getDisplayName() {
    return InspectionGadgetsBundle.message("disjoint.package.display.name");
  }

  @Override
  @Nullable
  public CommonProblemDescriptor[] checkElement(
    @NotNull RefEntity refEntity, @NotNull AnalysisScope analysisScope,
    @NotNull InspectionManager inspectionManager,
    @NotNull GlobalInspectionContext globalInspectionContext) {
    if (!(refEntity instanceof RefPackage)) {
      return null;
    }
    final RefPackage refPackage = (RefPackage)refEntity;
    final List children = refPackage.getChildren();
    if (children == null) {
      return null;
    }
    final Set childClasses = new HashSet();
    for (RefEntity child : children) {
      if (!(child instanceof RefClass)) {
        continue;
      }
      final PsiClass psiClass = ((RefClass)child).getElement();
      if (ClassUtils.isInnerClass(psiClass)) {
        continue;
      }
      childClasses.add((RefClass)child);
    }
    if (childClasses.isEmpty()) {
      return null;
    }
    final Set> components =
      createComponents(refPackage, childClasses);
    if (components.size() == 1) {
      return null;
    }
    final String errorString = InspectionGadgetsBundle
      .message("disjoint.package.problem.descriptor",
               refPackage.getQualifiedName(),
               Integer.valueOf(components.size()));

    return new CommonProblemDescriptor[]{
      inspectionManager.createProblemDescriptor(errorString)};
  }

  private static Set> createComponents(
    RefPackage aPackage, Set classes) {
    final Set allClasses = new HashSet(classes);
    final Set> out = new HashSet>();
    while (!allClasses.isEmpty()) {
      final RefClass seed = allClasses.iterator().next();
      allClasses.remove(seed);
      final Set currentComponent = new HashSet();
      currentComponent.add(seed);
      final List pendingClasses = new ArrayList();
      pendingClasses.add(seed);
      while (!pendingClasses.isEmpty()) {
        final RefClass classToProcess = pendingClasses.remove(0);
        final Set relatedClasses =
          getRelatedClasses(aPackage, classToProcess);
        for (RefClass relatedClass : relatedClasses) {
          if (!currentComponent.contains(relatedClass) &&
              !pendingClasses.contains(relatedClass)) {
            currentComponent.add(relatedClass);
            pendingClasses.add(relatedClass);
            allClasses.remove(relatedClass);
          }
        }
      }
      out.add(currentComponent);
    }
    return out;
  }

  private static Set getRelatedClasses(RefPackage aPackage,
                                                 RefClass classToProcess) {
    final Set out = new HashSet();
    final Set dependencies =
      DependencyUtils.calculateDependenciesForClass(classToProcess);
    for (RefClass dependency : dependencies) {
      if (packageContainsClass(aPackage, dependency)) {
        out.add(dependency);
      }
    }

    final Set dependents =
      DependencyUtils.calculateDependentsForClass(classToProcess);
    for (RefClass dependent : dependents) {
      if (packageContainsClass(aPackage, dependent)) {
        out.add(dependent);
      }
    }
    return out;
  }

  private static boolean packageContainsClass(RefPackage aPackage,
                                              RefClass aClass) {
    return aPackage.equals(RefJavaUtil.getPackage(aClass));
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy