create more precise compilation scope when particular files are recompiled (IDEA-226671)

GitOrigin-RevId: f98ea005bc8ff097565dad3eb188d4987e92182a
This commit is contained in:
Eugene Zhuravlev
2019-11-23 13:11:22 +00:00
committed by intellij-monorepo-bot
parent 108e897cb4
commit bc0fca0187
7 changed files with 79 additions and 9 deletions
@@ -176,8 +176,8 @@ public class CompileDriver {
if (explicitScopes != null) {
scopes.addAll(explicitScopes);
}
else if (!compileContext.isRebuild() && !CompileScopeUtil.allProjectModulesAffected(compileContext)) {
CompileScopeUtil.addScopesForModules(Arrays.asList(scope.getAffectedModules()), scope.getAffectedUnloadedModules(), scopes, forceBuild);
else if (!compileContext.isRebuild() && (!paths.isEmpty() || !CompileScopeUtil.allProjectModulesAffected(compileContext))) {
CompileScopeUtil.addScopesForSourceSets(scope.getAffectedSourceSets(), scope.getAffectedUnloadedModules(), scopes, forceBuild);
}
else {
scopes.addAll(CmdlineProtoUtil.createAllModulesScopes(forceBuild));
@@ -15,6 +15,7 @@
*/
package com.intellij.compiler.impl;
import com.intellij.compiler.ModuleSourceSet;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Key;
@@ -68,6 +69,30 @@ public class CompileScopeUtil {
}
}
public static void addScopesForSourceSets(Collection<? extends ModuleSourceSet> sets, Collection<String> unloadedModules, List<? super TargetTypeBuildScope> scopes, boolean forceBuild) {
if (!sets.isEmpty() || !unloadedModules.isEmpty()) {
for (ModuleSourceSet set : sets) {
final BuildTargetType targetType = toTargetType(set);
assert targetType != null;
TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder().setTypeId(targetType.getTypeId()).setForceBuild(forceBuild);
builder.addTargetId(set.getModule().getName());
for (String unloadedModule : unloadedModules) {
builder.addTargetId(unloadedModule);
}
scopes.add(builder.build());
}
}
}
private static BuildTargetType toTargetType(ModuleSourceSet set) {
switch (set.getType()) {
case TEST: return JavaModuleBuildTargetType.TEST;
case PRODUCTION: return JavaModuleBuildTargetType.PRODUCTION;
default: return null;
}
}
public static List<TargetTypeBuildScope> getBaseScopeForExternalBuild(@NotNull CompileScope scope) {
return scope.getUserData(BASE_SCOPE_FOR_EXTERNAL_BUILD);
}
@@ -19,6 +19,7 @@
*/
package com.intellij.compiler.impl;
import com.intellij.compiler.ModuleSourceSet;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.ExportableUserDataHolderBase;
import com.intellij.openapi.fileTypes.FileType;
@@ -27,6 +28,7 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.SmartHashSet;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -91,6 +93,15 @@ public class CompositeScope extends ExportableUserDataHolderBase implements Comp
return modules.toArray(Module.EMPTY_ARRAY);
}
@Override
public Collection<ModuleSourceSet> getAffectedSourceSets() {
Set<ModuleSourceSet> sets = new SmartHashSet<>();
for (CompileScope scope : myScopes) {
sets.addAll(scope.getAffectedSourceSets());
}
return sets;
}
@NotNull
@Override
public Collection<String> getAffectedUnloadedModules() {
@@ -1,12 +1,12 @@
// Copyright 2000-2019 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.
package com.intellij.compiler.impl;
import com.intellij.compiler.ModuleSourceSet;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.ExportableUserDataHolderBase;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.ProjectFileIndex;
@@ -17,6 +17,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class OneProjectItemCompileScope extends ExportableUserDataHolderBase implements CompileScope{
@@ -58,12 +60,27 @@ public class OneProjectItemCompileScope extends ExportableUserDataHolderBase imp
@Override
@NotNull
public Module[] getAffectedModules() {
final Module module = ModuleUtilCore.findModuleForFile(myFile, myProject);
if (module == null) {
final Collection<ModuleSourceSet> sets = getAffectedSourceSets();
if (sets.isEmpty()) {
LOG.error("Module is null for file " + myFile.getPresentableUrl());
return Module.EMPTY_ARRAY;
}
return new Module[] {module};
return new Module[] {sets.iterator().next().getModule()};
}
@Override
public Collection<ModuleSourceSet> getAffectedSourceSets() {
if (myProject.isDefault()) {
return Collections.emptyList();
}
final ProjectFileIndex index = ProjectFileIndex.getInstance(myProject);
final Module module = index.getModuleForFile(myFile);
if (module == null) {
return Collections.emptyList();
}
return Collections.singleton(new ModuleSourceSet(
module,
index.isInTestSourceContent(myFile)? ModuleSourceSet.Type.TEST : ModuleSourceSet.Type.PRODUCTION
));
}
}
@@ -15,14 +15,17 @@
*/
package com.intellij.openapi.compiler;
import com.intellij.compiler.ModuleSourceSet;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Interface describing the current compilation scope.
@@ -67,4 +70,17 @@ public interface CompileScope extends ExportableUserDataHolder {
default Collection<String> getAffectedUnloadedModules() {
return Collections.emptyList();
}
/**
* @return similar to {getAffectedModules}, but is more precise about which kinds of source roots are affected: production and/or tests
*/
default Collection<ModuleSourceSet> getAffectedSourceSets() {
List<ModuleSourceSet> sets = new SmartList<>();
for (Module module : getAffectedModules()) {
for (ModuleSourceSet.Type setType : ModuleSourceSet.Type.values()) {
sets.add(new ModuleSourceSet(module, setType));
}
}
return sets;
}
}
@@ -70,7 +70,8 @@ public class ModuleCompileScopeTest extends BaseCompilerTestCase {
public void testForceCompileUpToDateFileAndDoNotCompileDependentTestClass() {
VirtualFile a = createFile("src/A.java", "class A{ public static void foo(int param) {} }");
VirtualFile b = createFile("testSrc/B.java", "class B { void bar() {A.foo(10);}}");
final String bText = "class B { void bar() {A.foo(10);}}";
VirtualFile b = createFile("testSrc/B.java", bText);
Module module = addModule("a", a.getParent(), b.getParent());
make(module);
assertOutput(module, fs().file("A.class"), false);
@@ -87,7 +88,7 @@ public class ModuleCompileScopeTest extends BaseCompilerTestCase {
deleteFile(testClassFile);
make(module);
assertOutput(module, fs());
changeFile(b); // touch b
changeFile(b, bText + " "); // touch b
compile(true, a);
assertOutput(module, fs().file("A.class"), false);
@@ -65,7 +65,7 @@ public class CompileScopeImpl extends CompileScope {
@Override
public boolean isWholeTargetAffected(@NotNull BuildTarget<?> target) {
return myFiles.isEmpty() && (myTypes.contains(target.getTargetType()) || myTargets.contains(target) || isAffectedByAssociatedModule(target));
return (myTypes.contains(target.getTargetType()) || myTargets.contains(target) || isAffectedByAssociatedModule(target)) && !myFiles.containsKey(target);
}
@Override