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
.openapi
.project
.Project
;
21 import com
.intellij
.psi
.PsiElement
;
22 import com
.intellij
.psi
.PsiFile
;
23 import com
.intellij
.psi
.impl
.PsiFileEx
;
24 import org
.jetbrains
.annotations
.NotNull
;
32 public abstract class DependenciesBuilder
{
33 private Project myProject
;
34 private final AnalysisScope myScope
;
35 private final AnalysisScope myScopeOfInterest
;
36 private final Map
<PsiFile
, Set
<PsiFile
>> myDependencies
= new HashMap
<PsiFile
, Set
<PsiFile
>>();
37 protected int myTotalFileCount
;
38 protected int myFileCount
= 0;
39 protected int myTransitive
= 0;
41 protected DependenciesBuilder(@NotNull final Project project
, @NotNull final AnalysisScope scope
) {
42 this(project
, scope
, null);
45 public DependenciesBuilder(final Project project
, final AnalysisScope scope
, final AnalysisScope scopeOfInterest
) {
48 myScopeOfInterest
= scopeOfInterest
;
49 myTotalFileCount
= scope
.getFileCount();
52 public void setInitialFileCount(final int fileCount
) {
53 myFileCount
= fileCount
;
56 public void setTotalFileCount(final int totalFileCount
) {
57 myTotalFileCount
= totalFileCount
;
60 public int getTotalFileCount() {
61 return myTotalFileCount
;
64 public Map
<PsiFile
, Set
<PsiFile
>> getDependencies() {
65 return myDependencies
;
68 public Map
<PsiFile
, Set
<PsiFile
>> getDirectDependencies() {
69 return getDependencies();
72 public AnalysisScope
getScope() {
76 public AnalysisScope
getScopeOfInterest() {
77 return myScopeOfInterest
;
80 public Project
getProject() {
84 public abstract String
getRootNodeNameInUsageView();
86 public abstract String
getInitialUsagesPosition();
88 public abstract boolean isBackward();
90 public abstract void analyze();
92 public Map
<PsiFile
, Map
<DependencyRule
, Set
<PsiFile
>>> getIllegalDependencies(){
93 Map
<PsiFile
, Map
<DependencyRule
, Set
<PsiFile
>>> result
= new HashMap
<PsiFile
, Map
<DependencyRule
, Set
<PsiFile
>>>();
94 DependencyValidationManager validator
= DependencyValidationManager
.getInstance(myProject
);
95 for (PsiFile file
: getDirectDependencies().keySet()) {
96 Set
<PsiFile
> deps
= getDirectDependencies().get(file
);
97 Map
<DependencyRule
, Set
<PsiFile
>> illegal
= null;
98 for (PsiFile dependency
: deps
) {
99 final DependencyRule rule
= isBackward() ?
100 validator
.getViolatorDependencyRule(dependency
, file
) :
101 validator
.getViolatorDependencyRule(file
, dependency
);
103 if (illegal
== null) {
104 illegal
= new HashMap
<DependencyRule
, Set
<PsiFile
>>();
105 result
.put(file
, illegal
);
107 Set
<PsiFile
> illegalFilesByRule
= illegal
.get(rule
);
108 if (illegalFilesByRule
== null) {
109 illegalFilesByRule
= new HashSet
<PsiFile
>();
111 illegalFilesByRule
.add(dependency
);
112 illegal
.put(rule
, illegalFilesByRule
);
119 public List
<List
<PsiFile
>> findPaths(PsiFile from
, PsiFile to
) {
120 return findPaths(from
, to
, new HashSet
<PsiFile
>());
123 private List
<List
<PsiFile
>> findPaths(PsiFile from
, PsiFile to
, Set
<PsiFile
> processed
) {
124 final List
<List
<PsiFile
>> result
= new ArrayList
<List
<PsiFile
>>();
125 final Set
<PsiFile
> reachable
= getDirectDependencies().get(from
);
126 if (reachable
!= null) {
127 if (reachable
.contains(to
)) {
128 final ArrayList
<PsiFile
> path
= new ArrayList
<PsiFile
>();
132 if (!processed
.contains(from
)) {
134 for (PsiFile file
: reachable
) {
135 if (!getScope().contains(file
)) { //exclude paths through scope
136 final List
<List
<PsiFile
>> paths
= findPaths(file
, to
, processed
);
137 for (List
<PsiFile
> path
: paths
) {
140 result
.addAll(paths
);
150 public static void analyzeFileDependencies(PsiFile file
, DependencyProcessor processor
) {
151 file
.putUserData(PsiFileEx
.BATCH_REFERENCE_PROCESSING
, Boolean
.TRUE
);
152 file
.accept(DependenciesVisitorFactory
.getInstance().createVisitor(processor
));
153 file
.putUserData(PsiFileEx
.BATCH_REFERENCE_PROCESSING
, null);
156 public boolean isTransitive() {
157 return myTransitive
> 0;
160 public int getTransitiveBorder() {
164 public interface DependencyProcessor
{
165 void process(PsiElement place
, PsiElement dependency
);