a2e62062c90dd51f33927ecbd5cf3fbaa0a990ae
[idea/community.git] / platform / projectModel-api / src / com / intellij / openapi / roots / OrderEnumerator.java
1 /*
2  * Copyright 2000-2017 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.openapi.roots;
17
18 import com.intellij.openapi.module.Module;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.roots.libraries.Library;
21 import com.intellij.openapi.util.Condition;
22 import com.intellij.openapi.vfs.VirtualFile;
23 import com.intellij.util.NotNullFunction;
24 import com.intellij.util.PathsList;
25 import com.intellij.util.Processor;
26 import org.jetbrains.annotations.NotNull;
27
28 import java.util.List;
29
30 /**
31  * <p>Interface for convenient processing dependencies of a module or a project. Allows to process {@link OrderEntry}s
32  * and collect classes and source roots.</p>
33  *
34  * <p>Use {@link #orderEntries(Module)} or {@link ModuleRootModel#orderEntries()} to process dependencies of a module
35  * and use {@link #orderEntries(Project)} to process dependencies of all modules in a project.</p>
36  *
37  * <p>Note that all configuration methods modify {@link OrderEnumerator} instance instead of creating a new one.</p>
38  *
39  * @author nik
40  */
41 public abstract class OrderEnumerator {
42   /**
43    * Skip test dependencies
44    *
45    * @return this instance
46    */
47   @NotNull
48   public abstract OrderEnumerator productionOnly();
49
50   /**
51    * Skip runtime-only dependencies
52    *
53    * @return this instance
54    */
55   @NotNull
56   public abstract OrderEnumerator compileOnly();
57
58   /**
59    * Skip compile-only dependencies
60    *
61    * @return this instance
62    */
63   @NotNull
64   public abstract OrderEnumerator runtimeOnly();
65
66   @NotNull
67   public abstract OrderEnumerator withoutSdk();
68
69   @NotNull
70   public abstract OrderEnumerator withoutLibraries();
71
72   @NotNull
73   public abstract OrderEnumerator withoutDepModules();
74
75   /**
76    * Skip root module's entries
77    * @return this
78    */
79   @NotNull
80   public abstract OrderEnumerator withoutModuleSourceEntries();
81
82   @NotNull
83   public OrderEnumerator librariesOnly() {
84     return withoutSdk().withoutDepModules().withoutModuleSourceEntries();
85   }
86
87   @NotNull
88   public OrderEnumerator sdkOnly() {
89     return withoutDepModules().withoutLibraries().withoutModuleSourceEntries();
90   }
91
92   @NotNull
93   public VirtualFile[] getAllLibrariesAndSdkClassesRoots() {
94     return withoutModuleSourceEntries().withoutDepModules().recursively().exportedOnly().classes().usingCache().getRoots();
95   }
96
97   @NotNull
98   public VirtualFile[] getAllSourceRoots() {
99     return recursively().exportedOnly().sources().usingCache().getRoots();
100   }
101
102   /**
103    * Recursively process modules on which the module depends. This flag is ignored for modules imported from Maven because for such modules
104    * transitive dependencies are propagated to the root module during importing.
105    *
106    * @return this instance
107    */
108   @NotNull
109   public abstract OrderEnumerator recursively();
110
111   /**
112    * Skip not exported dependencies. If this method is called after {@link #recursively()} direct non-exported dependencies won't be skipped
113    *
114    * @return this instance
115    */
116   @NotNull
117   public abstract OrderEnumerator exportedOnly();
118
119   /**
120    * Process only entries which satisfies the specified condition
121    *
122    * @param condition filtering condition
123    * @return this instance
124    */
125   @NotNull
126   public abstract OrderEnumerator satisfying(@NotNull Condition<? super OrderEntry> condition);
127
128   /**
129    * Use {@code provider.getRootModel()} to process module dependencies
130    *
131    * @param provider provider
132    * @return this instance
133    */
134   @NotNull
135   public abstract OrderEnumerator using(@NotNull RootModelProvider provider);
136
137   /**
138    * Determine if, given the current enumerator settings and handlers for a module, should the
139    * enumerator recurse to further modules based on the given ModuleOrderEntry?
140    *
141    * @param entry the ModuleOrderEntry in question (m1 -> m2)
142    * @param handlers custom handlers registered to the module
143    * @return true if the enumerator would have recursively processed the given ModuleOrderEntry.
144    */
145   public abstract boolean shouldRecurse(@NotNull ModuleOrderEntry entry, @NotNull List<? extends OrderEnumerationHandler> handlers);
146
147   /**
148    * @return {@link OrderRootsEnumerator} instance for processing classes roots
149    */
150   @NotNull
151   public abstract OrderRootsEnumerator classes();
152
153   /**
154    * @return {@link OrderRootsEnumerator} instance for processing source roots
155    */
156   @NotNull
157   public abstract OrderRootsEnumerator sources();
158
159   /**
160    * @param rootType root type
161    * @return {@link OrderRootsEnumerator} instance for processing roots of the specified type
162    */
163   @NotNull
164   public abstract OrderRootsEnumerator roots(@NotNull OrderRootType rootType);
165
166   /**
167    * @param rootTypeProvider custom root type provider
168    * @return {@link OrderRootsEnumerator} instance for processing roots of the provided type
169    */
170   @NotNull
171   public abstract OrderRootsEnumerator roots(@NotNull NotNullFunction<? super OrderEntry, ? extends OrderRootType> rootTypeProvider);
172
173   /**
174    * @return classes roots for all entries processed by this enumerator
175    */
176   @NotNull
177   public VirtualFile[] getClassesRoots() {
178     return classes().getRoots();
179   }
180
181   /**
182    * @return source roots for all entries processed by this enumerator
183    */
184   @NotNull
185   public VirtualFile[] getSourceRoots() {
186     return sources().getRoots();
187   }
188
189   /**
190    * @return list containing classes roots for all entries processed by this enumerator
191    */
192   @NotNull
193   public PathsList getPathsList() {
194     return classes().getPathsList();
195   }
196
197   /**
198    * @return list containing source roots for all entries processed by this enumerator
199    */
200   @NotNull
201   public PathsList getSourcePathsList() {
202     return sources().getPathsList();
203   }
204
205   /**
206    * Runs {@code processor.process()} for each entry processed by this enumerator.
207    *
208    * @param processor processor
209    */
210   public abstract void forEach(@NotNull Processor<? super OrderEntry> processor);
211
212   /**
213    * Runs {@code processor.process()} for each library processed by this enumerator.
214    *
215    * @param processor processor
216    */
217   public abstract void forEachLibrary(@NotNull Processor<? super Library> processor);
218
219   /**
220    * Runs {@code processor.process()} for each module processed by this enumerator.
221    *
222    * @param processor processor
223    */
224   public abstract void forEachModule(@NotNull Processor<? super Module> processor);
225
226   /**
227    * Passes order entries to the specified visitor.
228    *
229    * @param policy       the visitor to accept.
230    * @param initialValue the default value to be returned by the visit process.
231    * @return the value returned by the visitor.
232    * @see OrderEntry#accept(RootPolicy, Object)
233    */
234   public abstract <R> R process(@NotNull RootPolicy<R> policy, R initialValue);
235
236   /**
237    * Creates new enumerator instance to process dependencies of {@code module}
238    *
239    * @param module module
240    * @return new enumerator instance
241    */
242   @NotNull
243   public static OrderEnumerator orderEntries(@NotNull Module module) {
244     return ModuleRootManager.getInstance(module).orderEntries();
245   }
246
247   /**
248    * Creates new enumerator instance to process dependencies of all modules in {@code project}. Only first level dependencies of
249    * modules are processed so {@link #recursively()} option is ignored and {@link #withoutDepModules()} option is forced
250    *
251    * @param project project
252    * @return new enumerator instance
253    */
254   @NotNull
255   public static OrderEnumerator orderEntries(@NotNull Project project) {
256     return ProjectRootManager.getInstance(project).orderEntries();
257   }
258 }