Skip to content

Commit f407f8a

Browse files
committed
Perform a full build if output folder was deleted externally
If the output folder is deleted externally, Java builder doesn't rebuild anything on next auto / incremental build request. The change checks the missing output folder on the next build request and converts build kind to a FULL_BUILD if at least one output folder in the project is missing. Fixes eclipse-jdt#4745
1 parent be5a02e commit f407f8a

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

  • org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder

org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Map.Entry;
2929
import java.util.Set;
3030
import org.eclipse.core.resources.ICommand;
31+
import org.eclipse.core.resources.IContainer;
3132
import org.eclipse.core.resources.IMarker;
3233
import org.eclipse.core.resources.IProject;
3334
import org.eclipse.core.resources.IResource;
@@ -42,6 +43,7 @@
4243
import org.eclipse.jdt.core.IClasspathEntry;
4344
import org.eclipse.jdt.core.IJavaModelMarker;
4445
import org.eclipse.jdt.core.IJavaModelStatusConstants;
46+
import org.eclipse.jdt.core.IJavaProject;
4547
import org.eclipse.jdt.core.JavaCore;
4648
import org.eclipse.jdt.core.JavaModelException;
4749
import org.eclipse.jdt.core.compiler.CategorizedProblem;
@@ -686,6 +688,11 @@ private int initializeBuilder(int kind, boolean forBuild) throws CoreException {
686688
builtProjects = new LinkedHashSet<>();
687689
}
688690
builtProjects.add(projectName);
691+
692+
if (kind != CLEAN_BUILD) {
693+
// check if we need to switch to full build due to missing output folder(s)
694+
kind = checkOutputFolders(this.javaProject, kind);
695+
}
689696
}
690697

691698
this.binaryLocationsPerProject = new HashMap<>(3);
@@ -878,6 +885,55 @@ private void recordNewState(State state) {
878885
JavaModelManager.getJavaModelManager().setLastBuiltState(this.currentProject, state);
879886
}
880887

888+
/**
889+
* Checks whether all output folders for the given project exist on disk.
890+
*
891+
* @param project
892+
* The Java project to check
893+
* @return If any output folder is missing, {@link IncrementalProjectBuilder#FULL_BUILD} is returned and original
894+
* <code>buildKind</code> argument otherwise.
895+
*/
896+
protected int checkOutputFolders(IJavaProject project, int buildKind) {
897+
try {
898+
IWorkspaceRoot root = project.getProject().getWorkspace().getRoot();
899+
IContainer defaultOutputLocation = root.getFolder(project.getOutputLocation());
900+
boolean needsFullBuild = !existsOnDisk(defaultOutputLocation);
901+
if (needsFullBuild) {
902+
return FULL_BUILD;
903+
}
904+
905+
IClasspathEntry[] classpath = project.getRawClasspath();
906+
for (IClasspathEntry entry : classpath) {
907+
if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
908+
IPath outputLocation = entry.getOutputLocation();
909+
if (outputLocation != null) {
910+
IContainer outputFolder = root.getFolder(outputLocation);
911+
if (!existsOnDisk(outputFolder)) {
912+
needsFullBuild = true;
913+
break;
914+
}
915+
}
916+
}
917+
}
918+
919+
return needsFullBuild ? FULL_BUILD : buildKind;
920+
} catch (JavaModelException e) {
921+
// If we can't read the classpath, just return the original build kind
922+
return buildKind;
923+
}
924+
}
925+
926+
private boolean existsOnDisk(IContainer defaultOutputLocation) {
927+
boolean exists = defaultOutputLocation.exists();
928+
// Resource is not present in workspace model
929+
if (!exists) {
930+
return false;
931+
}
932+
// check that the folder *really* exists on disk and is a folder
933+
IPath location = defaultOutputLocation.getLocation();
934+
return location != null && location.toFile().isDirectory();
935+
}
936+
881937
/**
882938
* String representation for debugging purposes
883939
*/

0 commit comments

Comments
 (0)