NPE (18686)
[fedora-idea.git] / platform / lang-impl / src / com / intellij / packageDependencies / ForwardDependenciesBuilder.java
blob2fae6dbb14559bc3aaacf22081c5c557bf41b261
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.packageDependencies;
19 import com.intellij.analysis.AnalysisScope;
20 import com.intellij.analysis.AnalysisScopeBundle;
21 import com.intellij.openapi.progress.ProcessCanceledException;
22 import com.intellij.openapi.progress.ProgressIndicator;
23 import com.intellij.openapi.progress.ProgressManager;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.project.ProjectUtil;
26 import com.intellij.openapi.roots.ProjectFileIndex;
27 import com.intellij.openapi.roots.ProjectRootManager;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.psi.*;
30 import org.jetbrains.annotations.NotNull;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.Map;
35 import java.util.Set;
37 public class ForwardDependenciesBuilder extends DependenciesBuilder {
38 private final Map<PsiFile, Set<PsiFile>> myDirectDependencies = new HashMap<PsiFile, Set<PsiFile>>();
40 public ForwardDependenciesBuilder(@NotNull Project project, @NotNull AnalysisScope scope) {
41 super(project, scope);
44 public ForwardDependenciesBuilder(final Project project, final AnalysisScope scope, final AnalysisScope scopeOfInterest) {
45 super(project, scope, scopeOfInterest);
48 public ForwardDependenciesBuilder(final Project project, final AnalysisScope scope, final int transitive) {
49 super(project, scope);
50 myTransitive = transitive;
53 public String getRootNodeNameInUsageView(){
54 return AnalysisScopeBundle.message("forward.dependencies.usage.view.root.node.text");
57 public String getInitialUsagesPosition(){
58 return AnalysisScopeBundle.message("forward.dependencies.usage.view.initial.text");
61 public boolean isBackward(){
62 return false;
65 public void analyze() {
66 final PsiManager psiManager = PsiManager.getInstance(getProject());
67 psiManager.startBatchFilesProcessingMode();
68 final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(getProject()).getFileIndex();
69 try {
70 getScope().accept(new PsiRecursiveElementVisitor() {
71 @Override public void visitFile(final PsiFile file) {
72 visit(file, fileIndex, psiManager, 0);
74 });
76 finally {
77 psiManager.finishBatchFilesProcessingMode();
81 private void visit(final PsiFile file, final ProjectFileIndex fileIndex, final PsiManager psiManager, int depth) {
83 final FileViewProvider viewProvider = file.getViewProvider();
84 if (viewProvider.getBaseLanguage() != file.getLanguage()) return;
86 if (getScopeOfInterest() != null && !getScopeOfInterest().contains(file)) return;
88 ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
89 if (indicator != null) {
90 if (indicator.isCanceled()) {
91 throw new ProcessCanceledException();
93 indicator.setText(AnalysisScopeBundle.message("package.dependencies.progress.text"));
94 final VirtualFile virtualFile = file.getVirtualFile();
95 if (virtualFile != null) {
96 indicator.setText2(ProjectUtil.calcRelativeToProjectPath(virtualFile, getProject()));
98 if ( myTotalFileCount > 0) {
99 indicator.setFraction(((double)++ myFileCount) / myTotalFileCount);
103 final Set<PsiFile> collectedDeps = new HashSet<PsiFile>();
104 final HashSet<PsiFile> processed = new HashSet<PsiFile>();
105 collectedDeps.add(file);
106 do {
107 if (depth++ > getTransitiveBorder()) return;
108 for (PsiFile psiFile : new HashSet<PsiFile>(collectedDeps)) {
109 final Set<PsiFile> found = new HashSet<PsiFile>();
110 if (!processed.contains(psiFile)) {
111 processed.add(psiFile);
112 analyzeFileDependencies(psiFile, new DependencyProcessor() {
113 public void process(PsiElement place, PsiElement dependency) {
114 PsiFile dependencyFile = dependency.getContainingFile();
115 if (dependencyFile != null) {
116 if (viewProvider == dependencyFile.getViewProvider()) return;
117 if (dependencyFile.isPhysical()) {
118 final VirtualFile virtualFile = dependencyFile.getVirtualFile();
119 if (virtualFile != null &&
120 (fileIndex.isInContent(virtualFile) ||
121 fileIndex.isInLibraryClasses(virtualFile) ||
122 fileIndex.isInLibrarySource(virtualFile))) {
123 found.add(dependencyFile);
129 Set<PsiFile> deps = getDependencies().get(file);
130 if (deps == null) {
131 deps = new HashSet<PsiFile>();
132 getDependencies().put(file, deps);
134 deps.addAll(found);
136 getDirectDependencies().put(psiFile, new HashSet<PsiFile>(found));
138 collectedDeps.addAll(found);
140 psiManager.dropResolveCaches();
143 collectedDeps.removeAll(processed);
145 while (isTransitive() && !collectedDeps.isEmpty());
148 public Map<PsiFile, Set<PsiFile>> getDirectDependencies() {
149 return myDirectDependencies;