Cleanup: NotNull/Nullable
[idea/community.git] / java / compiler / impl / src / com / intellij / compiler / impl / CompileScopeUtil.java
1 /*
2  * Copyright 2000-2016 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.compiler.impl;
17
18 import com.intellij.openapi.compiler.CompileScope;
19 import com.intellij.openapi.module.Module;
20 import com.intellij.openapi.util.Key;
21 import com.intellij.openapi.vfs.VirtualFile;
22 import com.intellij.packaging.artifacts.Artifact;
23 import com.intellij.util.containers.ContainerUtil;
24 import org.jetbrains.annotations.NotNull;
25 import org.jetbrains.jps.api.CmdlineProtoUtil;
26 import org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
27 import org.jetbrains.jps.builders.BuildTargetType;
28 import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
29 import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTargetType;
30
31 import java.util.*;
32
33 /**
34  * @author nik
35  */
36 public class CompileScopeUtil {
37   private static final Key<List<TargetTypeBuildScope>> BASE_SCOPE_FOR_EXTERNAL_BUILD = Key.create("SCOPE_FOR_EXTERNAL_BUILD");
38
39   public static void setBaseScopeForExternalBuild(@NotNull CompileScope scope, @NotNull List<TargetTypeBuildScope> scopes) {
40     scope.putUserData(BASE_SCOPE_FOR_EXTERNAL_BUILD, scopes);
41   }
42
43   public static void setResourcesScopeForExternalBuild(@NotNull CompileScope scope, @NotNull List<String> moduleNames) {
44     List<TargetTypeBuildScope> resourceScopes = new ArrayList<>();
45     for (UpdateResourcesBuildContributor provider : UpdateResourcesBuildContributor.EP_NAME.getExtensions()) {
46       for (BuildTargetType<?> type : provider.getResourceTargetTypes()) {
47         resourceScopes.add(CmdlineProtoUtil.createTargetsScope(type.getTypeId(), moduleNames, false));
48       }
49     }
50     setBaseScopeForExternalBuild(scope, resourceScopes);
51   }
52
53   public static void addScopesForModules(Collection<? extends Module> modules,
54                                          Collection<String> unloadedModules,
55                                          List<? super TargetTypeBuildScope> scopes,
56                                          boolean forceBuild) {
57     if (!modules.isEmpty() || !unloadedModules.isEmpty()) {
58       for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) {
59         TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder().setTypeId(type.getTypeId()).setForceBuild(forceBuild);
60         for (Module module : modules) {
61           builder.addTargetId(module.getName());
62         }
63         for (String unloadedModule : unloadedModules) {
64           builder.addTargetId(unloadedModule);
65         }
66         scopes.add(builder.build());
67       }
68     }
69   }
70
71   public static List<TargetTypeBuildScope> getBaseScopeForExternalBuild(@NotNull CompileScope scope) {
72     return scope.getUserData(BASE_SCOPE_FOR_EXTERNAL_BUILD);
73   }
74
75   public static List<TargetTypeBuildScope> mergeScopes(List<TargetTypeBuildScope> scopes1, List<TargetTypeBuildScope> scopes2) {
76     if (scopes2.isEmpty()) return scopes1;
77     if (scopes1.isEmpty()) return scopes2;
78
79     Map<String, TargetTypeBuildScope> scopeById = new HashMap<>();
80     mergeScopes(scopeById, scopes1);
81     mergeScopes(scopeById, scopes2);
82     return new ArrayList<>(scopeById.values());
83   }
84
85   private static void mergeScopes(Map<String, TargetTypeBuildScope> scopeById, List<TargetTypeBuildScope> scopes) {
86     for (TargetTypeBuildScope scope : scopes) {
87       String id = scope.getTypeId();
88       TargetTypeBuildScope old = scopeById.get(id);
89       if (old == null) {
90         scopeById.put(id, scope);
91       }
92       else {
93         scopeById.put(id, mergeScope(old, scope));
94       }
95     }
96   }
97
98   private static TargetTypeBuildScope mergeScope(TargetTypeBuildScope scope1, TargetTypeBuildScope scope2) {
99     String typeId = scope1.getTypeId();
100     if (scope1.getAllTargets()) {
101       return !scope1.getForceBuild() && scope2.getForceBuild() ? createAllTargetForcedBuildScope(typeId) : scope1;
102     }
103     if (scope2.getAllTargets()) {
104       return !scope2.getForceBuild() && scope1.getForceBuild() ? createAllTargetForcedBuildScope(typeId) : scope2;
105     }
106     return TargetTypeBuildScope.newBuilder()
107       .setTypeId(typeId)
108       .setForceBuild(scope1.getForceBuild() || scope2.getForceBuild())
109       .addAllTargetId(scope1.getTargetIdList())
110       .addAllTargetId(scope2.getTargetIdList())
111       .build();
112   }
113
114   private static TargetTypeBuildScope createAllTargetForcedBuildScope(final String typeId) {
115     return TargetTypeBuildScope.newBuilder().setTypeId(typeId).setForceBuild(true).setAllTargets(true).build();
116   }
117
118   public static boolean allProjectModulesAffected(CompileContextImpl compileContext) {
119     final Set<Module> allModules = new HashSet<>(Arrays.asList(compileContext.getProjectCompileScope().getAffectedModules()));
120     allModules.removeAll(Arrays.asList(compileContext.getCompileScope().getAffectedModules()));
121     return allModules.isEmpty();
122   }
123
124   public static List<String> fetchFiles(CompileContextImpl context) {
125     if (context.isRebuild()) {
126       return Collections.emptyList();
127     }
128     final CompileScope scope = context.getCompileScope();
129     if (shouldFetchFiles(scope)) {
130       return ContainerUtil.map(scope.getFiles(null, true), VirtualFile::getPath);
131     }
132     return Collections.emptyList();
133   }
134
135   private static boolean shouldFetchFiles(CompileScope scope) {
136     if (scope instanceof CompositeScope) {
137       for (CompileScope compileScope : ((CompositeScope)scope).getScopes()) {
138         if (shouldFetchFiles(compileScope)) {
139           return true;
140         }
141       }
142     }
143     return scope instanceof OneProjectItemCompileScope || scope instanceof FileSetCompileScope;
144   }
145
146   public static TargetTypeBuildScope createScopeForArtifacts(Collection<Artifact> artifacts,
147                                                              boolean forceBuild) {
148     TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder()
149                                                                .setTypeId(ArtifactBuildTargetType.INSTANCE.getTypeId())
150                                                                .setForceBuild(
151                                                                  forceBuild);
152     for (Artifact artifact : artifacts) {
153       builder.addTargetId(artifact.getName());
154     }
155     return builder.build();
156   }
157 }