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
;
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(){
65 public void analyze() {
66 final PsiManager psiManager
= PsiManager
.getInstance(getProject());
67 psiManager
.startBatchFilesProcessingMode();
68 final ProjectFileIndex fileIndex
= ProjectRootManager
.getInstance(getProject()).getFileIndex();
70 getScope().accept(new PsiRecursiveElementVisitor() {
71 @Override public void visitFile(final PsiFile file
) {
72 visit(file
, fileIndex
, psiManager
, 0);
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
);
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
);
131 deps
= new HashSet
<PsiFile
>();
132 getDependencies().put(file
, deps
);
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
;