cleanup (inspection "Java | Class structure | Utility class is not 'final'")
[idea/community.git] / jps / jps-builders / src / org / jetbrains / jps / incremental / BuilderRegistry.java
1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package org.jetbrains.jps.incremental;
3
4 import com.intellij.openapi.diagnostic.Logger;
5 import com.intellij.openapi.util.io.FileUtil;
6 import com.intellij.openapi.util.io.FileUtilRt;
7 import gnu.trove.THashSet;
8 import gnu.trove.TObjectLongHashMap;
9 import org.jetbrains.annotations.NotNull;
10 import org.jetbrains.jps.builders.BuildTargetType;
11 import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
12 import org.jetbrains.jps.service.JpsServiceManager;
13
14 import java.io.FileFilter;
15 import java.util.*;
16
17 /**
18  * @author Eugene Zhuravlev
19  */
20 public class BuilderRegistry {
21   private static final Logger LOG = Logger.getInstance(BuilderRegistry.class);
22   private static final class Holder {
23     static final BuilderRegistry ourInstance = new BuilderRegistry();
24   }
25   private final Map<BuilderCategory, List<ModuleLevelBuilder>> myModuleLevelBuilders = new HashMap<>();
26   private final TObjectLongHashMap<BuildTargetType<?>> myExpectedBuildTime = new TObjectLongHashMap<>();
27   private final List<TargetBuilder<?,?>> myTargetBuilders = new ArrayList<>();
28   private final FileFilter myModuleBuilderFileFilter;
29
30   public static BuilderRegistry getInstance() {
31     return Holder.ourInstance;
32   }
33
34   private BuilderRegistry() {
35     for (BuilderCategory category : BuilderCategory.values()) {
36       myModuleLevelBuilders.put(category, new ArrayList<>());
37     }
38
39     Set<String> compilableFileExtensions = new THashSet<>(FileUtil.PATH_HASHING_STRATEGY);
40     for (BuilderService service : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) {
41       myTargetBuilders.addAll(service.createBuilders());
42       final List<? extends ModuleLevelBuilder> moduleLevelBuilders = service.createModuleLevelBuilders();
43       for (ModuleLevelBuilder builder : moduleLevelBuilders) {
44         try {
45           List<String> extensions = builder.getCompilableFileExtensions();
46           if (compilableFileExtensions != null) {
47             compilableFileExtensions.addAll(extensions);
48           }
49         }
50         catch (AbstractMethodError e) {
51           LOG.info(builder.getClass().getName() + " builder doesn't implement 'getCompilableFileExtensions' method so ModuleBuildTarget will process all files under source roots.");
52           compilableFileExtensions = null;
53         }
54         myModuleLevelBuilders.get(builder.getCategory()).add(builder);
55       }
56     }
57     if (compilableFileExtensions == null) {
58       myModuleBuilderFileFilter = FileUtilRt.ALL_FILES;
59     }
60     else {
61       final Set<String> finalCompilableFileExtensions = compilableFileExtensions;
62       myModuleBuilderFileFilter = file -> finalCompilableFileExtensions.contains(FileUtilRt.getExtension(file.getName()));
63     }
64
65     long moduleTargetBuildTime = 0;
66     for (ModuleLevelBuilder builder : getModuleLevelBuilders()) {
67       moduleTargetBuildTime += builder.getExpectedBuildTime();
68     }
69     myExpectedBuildTime.put(JavaModuleBuildTargetType.PRODUCTION, moduleTargetBuildTime);
70     myExpectedBuildTime.put(JavaModuleBuildTargetType.TEST, moduleTargetBuildTime);
71
72     for (TargetBuilder<?, ?> targetBuilder : myTargetBuilders) {
73       long buildTime = targetBuilder.getExpectedBuildTime();
74       for (BuildTargetType<?> type : targetBuilder.getTargetTypes()) {
75         if (!myExpectedBuildTime.adjustValue(type, buildTime)) {
76           myExpectedBuildTime.put(type, buildTime);
77         }
78       }
79     }
80   }
81
82   @NotNull
83   public FileFilter getModuleBuilderFileFilter() {
84     return myModuleBuilderFileFilter;
85   }
86
87   public int getModuleLevelBuilderCount() {
88     int count = 0;
89     for (BuilderCategory category : BuilderCategory.values()) {
90       count += getBuilders(category).size();
91     }
92     return count;
93   }
94
95   public List<BuildTask> getBeforeTasks(){
96     return Collections.emptyList(); // todo
97   }
98
99   public List<BuildTask> getAfterTasks(){
100     return Collections.emptyList(); // todo
101   }
102
103   public List<ModuleLevelBuilder> getBuilders(BuilderCategory category){
104     return Collections.unmodifiableList(myModuleLevelBuilders.get(category));
105   }
106
107   public List<ModuleLevelBuilder> getModuleLevelBuilders() {
108     List<ModuleLevelBuilder> result = new ArrayList<>();
109     for (BuilderCategory category : BuilderCategory.values()) {
110       result.addAll(getBuilders(category));
111     }
112     return result;
113   }
114
115   public List<TargetBuilder<?,?>> getTargetBuilders() {
116     return myTargetBuilders;
117   }
118
119   /**
120    * Returns default expected build time for targets of the given {@code targetType}.
121    * @see Builder#getExpectedBuildTime()
122    */
123   public long getExpectedBuildTimeForTarget(BuildTargetType<?> targetType) {
124     long time = myExpectedBuildTime.get(targetType);
125     if (time == -1) {
126       //it may happen that there is no builders registered for a given type, so it won't be built at all.
127       return 0;
128     }
129     return time;
130   }
131 }