mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Mark as 'deleted' all non-existent paths obtained from dependency caches. This will automatically clean stale non-existent paths from dependency data in situations when deleted paths info for build targets is lost or not available (fixes problem when old target caches are lost and non-existing files from dependency caches are sent to compilation: IDEA-185750)
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
Compiling files:
|
||||
moduleB/src/ppp/Impl1.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/moduleA/ppp/Iface.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/ppp/Iface.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/moduleB_renamed/ppp/Impl1.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/ppp/Impl1.java
|
||||
End of files
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public interface Iface {
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ppp;
|
||||
|
||||
public interface Iface {
|
||||
void foo();
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl1 implements Iface{
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl1 implements Iface{
|
||||
public void foo() {}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl2 implements Iface{
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl2 implements Iface{
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
Compiling files:
|
||||
moduleA/src/ppp/Iface.java
|
||||
moduleA/src/ppp/Impl1.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/moduleA_renamed/ppp/Impl1.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/ppp/Impl1.java
|
||||
End of files
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public interface Iface {
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ppp;
|
||||
|
||||
public interface Iface {
|
||||
void foo();
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl1 implements Iface{
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl1 implements Iface{
|
||||
public void foo() {}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl2 implements Iface{
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package ppp;
|
||||
|
||||
public class Impl2 implements Iface{
|
||||
}
|
||||
@@ -272,7 +272,7 @@ public class JavaBuilderUtil {
|
||||
FSOperations.markDirty(context, markDirtyRound, chunk, null);
|
||||
}
|
||||
}
|
||||
additionalPassRequired = compilingIncrementally && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
|
||||
additionalPassRequired = compilingIncrementally && moduleBasedFilter.containsFilesFromCurrentTargetChunk(newlyAffectedFiles);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -354,13 +354,11 @@ public class JavaBuilderUtil {
|
||||
}
|
||||
|
||||
private static void removeFilesAcceptedByFilter(@NotNull Set<File> files, @Nullable FileFilter filter) {
|
||||
if (filter == null) return;
|
||||
|
||||
Iterator<File> iterator = files.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
File next = iterator.next();
|
||||
if (filter.accept(next)) {
|
||||
iterator.remove();
|
||||
if (filter != null) {
|
||||
for (final Iterator<File> it = files.iterator(); it.hasNext();) {
|
||||
if (filter.accept(it.next())) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,38 +374,21 @@ public class JavaBuilderUtil {
|
||||
return scope.isBuildIncrementally(JavaModuleBuildTargetType.PRODUCTION) || scope.isBuildIncrementally(JavaModuleBuildTargetType.TEST);
|
||||
}
|
||||
|
||||
private static List<Pair<File, JpsModule>> checkAffectedFilesInCorrectModules(CompileContext context,
|
||||
Collection<File> affected,
|
||||
ModulesBasedFileFilter moduleBasedFilter) {
|
||||
private static List<Pair<File, JpsModule>> checkAffectedFilesInCorrectModules(CompileContext context, Collection<File> affected, ModulesBasedFileFilter moduleBasedFilter) {
|
||||
if (affected.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<Pair<File, JpsModule>> result = new ArrayList<>();
|
||||
final BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex();
|
||||
for (File file : affected) {
|
||||
if (!moduleBasedFilter.accept(file)) {
|
||||
final JavaSourceRootDescriptor moduleAndRoot = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context,
|
||||
file);
|
||||
final JavaSourceRootDescriptor moduleAndRoot = rootIndex.findJavaRootDescriptor(context, file);
|
||||
result.add(Pair.create(file, moduleAndRoot != null ? moduleAndRoot.target.getModule() : null));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set<File> affected)
|
||||
throws IOException {
|
||||
final Set<JpsModule> chunkModules = chunk.getModules();
|
||||
if (!chunkModules.isEmpty()) {
|
||||
for (File file : affected) {
|
||||
final JavaSourceRootDescriptor moduleAndRoot = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context,
|
||||
file);
|
||||
if (moduleAndRoot != null && chunkModules.contains(moduleAndRoot.target.getModule())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<File> getFilesContainer(CompileContext context, final Key<Set<File>> dataKey) {
|
||||
Set<File> files = dataKey.get(context);
|
||||
@@ -510,6 +491,15 @@ public class JavaBuilderUtil {
|
||||
final JavaSourceRootDescriptor rd = myBuildRootIndex.findJavaRootDescriptor(myContext, file);
|
||||
return rd != null && myChunkTargets.contains(rd.target);
|
||||
}
|
||||
|
||||
public boolean containsFilesFromCurrentTargetChunk(Collection<File> files) {
|
||||
for (File file : files) {
|
||||
if (belongsToCurrentTargetChunk(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NegationFileFilter implements FileFilter {
|
||||
|
||||
@@ -76,7 +76,6 @@ public class BuildOperations {
|
||||
|
||||
// handle deleted paths
|
||||
final BuildFSState fsState = pd.fsState;
|
||||
fsState.clearDeletedPaths(target);
|
||||
final SourceToOutputMapping sourceToOutputMap = pd.dataManager.getSourceToOutputMap(target);
|
||||
for (final Iterator<String> it = sourceToOutputMap.getSourcesIterator(); it.hasNext(); ) {
|
||||
final String path = it.next();
|
||||
|
||||
@@ -188,8 +188,20 @@ public final class FilesDelta {
|
||||
public boolean markRecompileIfNotDeleted(BuildRootDescriptor root, File file) {
|
||||
lockData();
|
||||
try {
|
||||
final boolean isMarkedDeleted = !myDeletedPaths.isEmpty() && myDeletedPaths.contains(FileUtil.toCanonicalPath(file.getPath()));
|
||||
String path = null;
|
||||
final boolean isMarkedDeleted = !myDeletedPaths.isEmpty() && myDeletedPaths.contains(path = FileUtil.toCanonicalPath(file.getPath()));
|
||||
if (!isMarkedDeleted) {
|
||||
if (!file.exists()) {
|
||||
// incorrect paths data recovery, so that the next make should not contain non-existing sources in 'recompile' list
|
||||
if (path == null) {
|
||||
path = FileUtil.toCanonicalPath(file.getPath());
|
||||
}
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Marking deleted: " + path);
|
||||
}
|
||||
myDeletedPaths.add(path);
|
||||
return false;
|
||||
}
|
||||
_addToRecompiled(root, file);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -315,13 +315,13 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
compiledOk = compileJava(context, chunk, files, classpath, platformCp, srcPath, diagnosticSink, outputSink, compilingTool, hasModules);
|
||||
}
|
||||
finally {
|
||||
// heuristic: incorrect paths data recovery, so that the next make should not contain non-existing sources in 'recompile' list
|
||||
filesWithErrors = diagnosticSink.getFilesWithErrors();
|
||||
for (File file : filesWithErrors) {
|
||||
if (!file.exists()) {
|
||||
FSOperations.markDeleted(context, file);
|
||||
}
|
||||
}
|
||||
// heuristic: incorrect paths data recovery, so that the next make should not contain non-existing sources in 'recompile' list
|
||||
//for (File file : filesWithErrors) {
|
||||
// if (!file.exists()) {
|
||||
// FSOperations.markDeleted(context, file);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -156,16 +156,34 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase {
|
||||
return addModule(moduleName, new String[]{srcPath}, null, null, getOrCreateJdk());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the test changes project model between makes (e.g. module renamed), the descriptor should be re-created before each build session
|
||||
* in order to ensure the project is loaded correctly. If project model is unchanged, teh project descriptor can be reused from the previous build session
|
||||
* @return true if project descriptor from previous session can be reused, false otherwise
|
||||
*/
|
||||
protected boolean useCachedProjectDescriptorOnEachMake() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected BuildResult doTestBuild(int makesCount) {
|
||||
StringBuilder log = new StringBuilder();
|
||||
String rootPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/";
|
||||
final ProjectDescriptor pd = createProjectDescriptor(new BuildLoggingManager(new StringProjectBuilderLogger(rootPath, log)));
|
||||
ProjectDescriptor pd = createProjectDescriptor(new BuildLoggingManager(new StringProjectBuilderLogger(rootPath, log)));
|
||||
BuildResult result = null;
|
||||
try {
|
||||
final boolean reuseProjectId = useCachedProjectDescriptorOnEachMake();
|
||||
|
||||
doBuild(pd, CompileScopeTestBuilder.rebuild().allModules()).assertSuccessful();
|
||||
|
||||
for (int idx = 0; idx < makesCount; idx++) {
|
||||
// this will save the current build data state before any changes were done to the project model
|
||||
if (!reuseProjectId) {
|
||||
pd.release();
|
||||
}
|
||||
modify(idx);
|
||||
if (!reuseProjectId) {
|
||||
pd = createProjectDescriptor(new BuildLoggingManager(new StringProjectBuilderLogger(rootPath, log)));
|
||||
}
|
||||
result = doBuild(pd, CompileScopeTestBuilder.make().allModules());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2000-2018 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 org.jetbrains.ether;
|
||||
|
||||
import org.jetbrains.jps.model.JpsModuleRootModificationUtil;
|
||||
import org.jetbrains.jps.model.module.JpsModule;
|
||||
|
||||
public class RenameModuleTest extends IncrementalTestCase {
|
||||
JpsModule myModuleToRename;
|
||||
|
||||
public RenameModuleTest() {
|
||||
super("renameModule");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myModuleToRename = null;
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void modify(int stage) {
|
||||
if (stage == 0) {
|
||||
final JpsModule toRename = myModuleToRename;
|
||||
if (toRename != null) {
|
||||
myModuleToRename = null;
|
||||
final String name = toRename.getName();
|
||||
toRename.setName(name + "_renamed");
|
||||
}
|
||||
}
|
||||
super.modify(stage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useCachedProjectDescriptorOnEachMake() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void testDeleteClassSameModule() {
|
||||
myModuleToRename = addModule("moduleA", "moduleA/src");
|
||||
doTestBuild(1).assertSuccessful();
|
||||
}
|
||||
|
||||
public void testDeleteClassDependentModule() {
|
||||
JpsModule moduleA = addModule("moduleA", "moduleA/src");
|
||||
JpsModule moduleB = addModule("moduleB", "moduleB/src");
|
||||
JpsModuleRootModificationUtil.addDependency(moduleB, moduleA);
|
||||
myModuleToRename = moduleB;
|
||||
doTestBuild(2).assertSuccessful();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user