mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
cyclic dependencies cleaning
This commit is contained in:
@@ -1,18 +1,15 @@
|
||||
package com.intellij.cyclicDependencies;
|
||||
|
||||
import com.intellij.analysis.AnalysisScope;
|
||||
import com.intellij.compiler.Chunk;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.packageDependencies.ForwardDependenciesBuilder;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.graph.CachingSemiGraph;
|
||||
import com.intellij.util.graph.DFSTBuilder;
|
||||
import com.intellij.util.graph.Graph;
|
||||
import com.intellij.util.graph.GraphGenerator;
|
||||
|
||||
@@ -189,132 +186,29 @@ public class CyclicDependenciesBuilder{
|
||||
return result;
|
||||
}
|
||||
|
||||
/*public Set<PsiFile> getDependentFilesInPackage(PsiPackage pack, PsiPackage depPack) {
|
||||
final Set<PsiFile> result = new HashSet<PsiFile>();
|
||||
final Map<PsiFile, Set<PsiFile>> dependencies = myForwardBuilder.getDependencies();
|
||||
final Set<PsiFile> allPsiPackageFiles = getAllPsiPackageFiles(pack);
|
||||
for (Iterator<PsiFile> it = allPsiPackageFiles.iterator(); it.hasNext();) {
|
||||
PsiFile file = it.next();
|
||||
final Set<PsiFile> psiFiles = dependencies.get(file);
|
||||
if (psiFiles == null){
|
||||
continue;
|
||||
}
|
||||
for (Iterator<PsiFile> iterator = psiFiles.iterator(); iterator.hasNext();) {
|
||||
PsiFile psiFile = iterator.next();
|
||||
if (psiFile.getContainingDirectory().getPackage().getQualifiedName().startsWith(depPack.getQualifiedName())){
|
||||
result.add(psiFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<PsiFile> getDependentFilesInPackage(PsiPackage firstPack, PsiPackage middlePack, PsiPackage lastPack) {
|
||||
Set<PsiFile> result = new HashSet<PsiFile>();
|
||||
|
||||
final Map<PsiFile, Set<PsiFile>> dependencies = myForwardBuilder.getDependencies();
|
||||
final Set<PsiFile> allPsiPackageFiles = getAllPsiPackageFiles(middlePack);
|
||||
|
||||
for (Iterator<PsiFile> it = allPsiPackageFiles.iterator(); it.hasNext();) {
|
||||
PsiFile file = it.next();
|
||||
final Set<PsiFile> psiFiles = dependencies.get(file);
|
||||
if (psiFiles == null){
|
||||
continue;
|
||||
}
|
||||
for (Iterator<PsiFile> iterator = psiFiles.iterator(); iterator.hasNext();) {
|
||||
PsiFile psiFile = iterator.next();
|
||||
if (psiFile.getContainingDirectory().getPackage().getQualifiedName().startsWith(lastPack.getQualifiedName())){
|
||||
result.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.addAll(getDependentFilesInPackage(firstPack, middlePack));
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<PsiFile> getAllPsiPackageFiles(PsiPackage aPackage){
|
||||
Set<PsiFile> result = new HashSet<PsiFile>();
|
||||
final PsiDirectory[] directories = aPackage.getDirectories();
|
||||
if (directories == null){
|
||||
return result;
|
||||
}
|
||||
for (int i = 0; i < directories.length; i++) {
|
||||
PsiDirectory directory = directories[i];
|
||||
final PsiFile[] files = directory.getFiles();
|
||||
if (files == null){
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < files.length; j++) {
|
||||
PsiFile file = files[j];
|
||||
if (getScope().contains(file)){
|
||||
result.add(file);
|
||||
}
|
||||
}
|
||||
final PsiDirectory[] subdirectories = directory.getSubdirectories();
|
||||
if (subdirectories == null){
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < subdirectories.length; j++) {
|
||||
PsiDirectory subdirectory = subdirectories[j];
|
||||
result.addAll(getAllPsiPackageFiles(subdirectory.getPackage()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
public HashMap<PsiPackage, Set<List<PsiPackage>>> getCyclicDependencies() {
|
||||
return myCyclicDependencies;
|
||||
}
|
||||
|
||||
public HashMap<PsiPackage, Set<List<PsiPackage>>> getCycles(Collection<PsiPackage> packages) {
|
||||
if (myGraph == null){
|
||||
myGraph = buildGraph();
|
||||
}
|
||||
final HashMap<PsiPackage, Set<List<PsiPackage>>> result = new HashMap<PsiPackage, Set<List<PsiPackage>>>();
|
||||
final List<Chunk<PsiPackage>> chunks = buildChunks();
|
||||
for (Iterator<PsiPackage> iterator = packages.iterator(); iterator.hasNext();) {
|
||||
PsiPackage psiPackage = iterator.next();
|
||||
final List<Chunk<PsiPackage>> chunksByPackage = findChunksByPackage(psiPackage, chunks);
|
||||
for (Iterator<Chunk<PsiPackage>> it = chunksByPackage.iterator(); it.hasNext();) {
|
||||
Chunk<PsiPackage> chunk = it.next();
|
||||
if (chunk.getNodes().size() == 1){
|
||||
continue;
|
||||
}
|
||||
Set<List<PsiPackage>> paths2Pack = result.get(psiPackage);
|
||||
if (paths2Pack == null) {
|
||||
paths2Pack = new HashSet<List<PsiPackage>>();
|
||||
result.put(psiPackage, paths2Pack);
|
||||
}
|
||||
paths2Pack.addAll(CyclicGraphUtil.getNodeCycles(myGraph, psiPackage));
|
||||
/*final CyclicDependenciesUtil.GraphTraverser<PsiPackage> graphTraverser = new CyclicDependenciesUtil.GraphTraverser(psiPackage, chunk, 10, myGraph);
|
||||
paths2Pack.addAll(graphTraverser.convert(graphTraverser.traverse()));*/
|
||||
}
|
||||
}
|
||||
/*for (Iterator<Chunk<PsiPackage>> iterator = chunks.iterator(); iterator.hasNext();) {
|
||||
Chunk<PsiPackage> chunk = iterator.next();
|
||||
for (Iterator<PsiPackage> it = chunk.getNodes().iterator(); it.hasNext();) {
|
||||
PsiPackage pack = it.next();
|
||||
Set<Chunk<PsiPackage>> chunks2Pack = result.get(pack);
|
||||
if (chunks2Pack == null) {
|
||||
chunks2Pack = new HashSet<Chunk<PsiPackage>>();
|
||||
result.put(pack, chunks2Pack);
|
||||
}
|
||||
chunks2Pack.add(chunk);
|
||||
}
|
||||
|
||||
}*/
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Chunk<PsiPackage>> findChunksByPackage(PsiPackage pack, List<Chunk<PsiPackage>> chunks) {
|
||||
List<Chunk<PsiPackage>> result = new ArrayList<Chunk<PsiPackage>>();
|
||||
for (Iterator<Chunk<PsiPackage>> iterator = chunks.iterator(); iterator.hasNext();) {
|
||||
Chunk<PsiPackage> chunk = iterator.next();
|
||||
if (chunk.containsNode(pack)) {
|
||||
result.add(chunk);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<String, PsiPackage> getAllProjectPackages() {
|
||||
public Map<String, PsiPackage> getAllScopePackages() {
|
||||
if (myPackages.isEmpty()) {
|
||||
final PsiManager psiManager = PsiManager.getInstance(getProject());
|
||||
getScope().accept(new PsiRecursiveElementVisitor() {
|
||||
@@ -336,7 +230,7 @@ public class CyclicDependenciesBuilder{
|
||||
private Graph<PsiPackage> buildGraph() {
|
||||
final Graph<PsiPackage> graph = GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<PsiPackage>() {
|
||||
public Collection<PsiPackage> getNodes() {
|
||||
return getAllProjectPackages().values();
|
||||
return getAllScopePackages().values();
|
||||
}
|
||||
|
||||
public Iterator<PsiPackage> getIn(PsiPackage psiPack) {
|
||||
@@ -371,30 +265,8 @@ public class CyclicDependenciesBuilder{
|
||||
}
|
||||
|
||||
private PsiPackage findPackage(String packName) {
|
||||
final PsiPackage psiPackage = getAllProjectPackages().get(packName);
|
||||
final PsiPackage psiPackage = getAllScopePackages().get(packName);
|
||||
return psiPackage;
|
||||
}
|
||||
|
||||
private List<Chunk<PsiPackage>> buildChunks() {
|
||||
if (myGraph == null) {
|
||||
myGraph = buildGraph();
|
||||
}
|
||||
final DFSTBuilder<PsiPackage> dfstBuilder = new DFSTBuilder<PsiPackage>(myGraph);
|
||||
dfstBuilder.buildDFST();
|
||||
final LinkedList<Pair<Integer, Integer>> sccs = dfstBuilder.getSCCs();
|
||||
List<Chunk<PsiPackage>> chunks = new ArrayList<Chunk<PsiPackage>>();
|
||||
for (Iterator<Pair<Integer, Integer>> i = sccs.iterator(); i.hasNext();) {
|
||||
Set<PsiPackage> packs = new HashSet<PsiPackage>();
|
||||
final Pair<Integer, Integer> p = i.next();
|
||||
final Integer biT = p.getFirst();
|
||||
final int binum = biT.intValue();
|
||||
|
||||
for (int j = 0; j < p.getSecond().intValue(); j++) {
|
||||
packs.add(dfstBuilder.getNodeByTNumber(binum + j));
|
||||
}
|
||||
chunks.add(new Chunk<PsiPackage>(packs));
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,13 +2,9 @@ package com.intellij.cyclicDependencies.ui;
|
||||
|
||||
import com.intellij.packageDependencies.ui.PackageDependenciesNode;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.MutableTreeNode;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.util.Set;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
@@ -20,7 +16,7 @@ public class CycleNode extends PackageDependenciesNode{
|
||||
}
|
||||
|
||||
public void addFile(PsiFile file, boolean isMarked) {
|
||||
super.addFile(file, isMarked); //To change body of overridden methods use File | Settings | File Templates.
|
||||
super.addFile(file, isMarked);
|
||||
}
|
||||
|
||||
public Icon getOpenIcon() {
|
||||
|
||||
@@ -362,10 +362,6 @@ public class CyclicDependenciesPanel extends JPanel {
|
||||
else {
|
||||
setIcon(node.getClosedIcon());
|
||||
}
|
||||
|
||||
if (node.hasMarked() && !selected) {
|
||||
setForeground(Color.red);
|
||||
}
|
||||
append(node.toString(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.a;
|
||||
public class A{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.b;
|
||||
import com.a.A;
|
||||
public class B{
|
||||
A aa = new A();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.a;
|
||||
import com.b.B1;
|
||||
public class A{
|
||||
B1 b = new B1();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.b;
|
||||
public class B1{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.b;
|
||||
import com.c.C;
|
||||
public class B2{
|
||||
C cc= new C();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.c;
|
||||
import com.a.A;
|
||||
public class C{
|
||||
A aa = new A();
|
||||
}
|
||||
@@ -130,6 +130,33 @@ public class CyclicDependenciesTest extends PsiTestCase {
|
||||
checkResult(expected, cyclicDependencies, true);
|
||||
}
|
||||
|
||||
public void testT6() {
|
||||
//A->B1
|
||||
//B2->C
|
||||
//C->A
|
||||
final CyclicDependenciesBuilder builder = new CyclicDependenciesBuilder(myProject,
|
||||
new AnalysisScope(myProject, AnalysisScope.SOURCE_JAVA_FILES));
|
||||
builder.analyze();
|
||||
final HashMap<PsiPackage, Set<List<PsiPackage>>> cyclicDependencies = builder.getCyclicDependencies();
|
||||
HashMap<String, String[][]> expected = new HashMap<String, String[][]>();
|
||||
expected.put("com.b", new String[][]{{"com.a", "com.c", "com.b"}});
|
||||
expected.put("com.c", new String[][]{{"com.b", "com.a", "com.c"}});
|
||||
expected.put("com.a", new String[][]{{"com.c", "com.b", "com.a"}});
|
||||
checkResult(expected, cyclicDependencies, true);
|
||||
}
|
||||
|
||||
public void testNoCycle(){
|
||||
//B->A
|
||||
final CyclicDependenciesBuilder builder = new CyclicDependenciesBuilder(myProject,
|
||||
new AnalysisScope(myProject, AnalysisScope.SOURCE_JAVA_FILES));
|
||||
builder.analyze();
|
||||
final HashMap<PsiPackage, Set<List<PsiPackage>>> cyclicDependencies = builder.getCyclicDependencies();
|
||||
HashMap<String, String[][]> expected = new HashMap<String, String[][]>();
|
||||
expected.put("com.b", new String[0][0]);
|
||||
expected.put("com.a", new String[0][0]);
|
||||
checkResult(expected, cyclicDependencies, true);
|
||||
}
|
||||
|
||||
private void checkResult(HashMap<String, String[][]> expected, HashMap<PsiPackage, Set<List<PsiPackage>>> cycles) {
|
||||
assertEquals(expected.size(), cycles.size());
|
||||
Iterator<PsiPackage> it = cycles.keySet().iterator();
|
||||
|
||||
Reference in New Issue
Block a user