|
28 | 28 | import java.util.Map.Entry; |
29 | 29 | import java.util.Set; |
30 | 30 | import org.eclipse.core.resources.ICommand; |
| 31 | +import org.eclipse.core.resources.IContainer; |
31 | 32 | import org.eclipse.core.resources.IMarker; |
32 | 33 | import org.eclipse.core.resources.IProject; |
33 | 34 | import org.eclipse.core.resources.IResource; |
|
42 | 43 | import org.eclipse.jdt.core.IClasspathEntry; |
43 | 44 | import org.eclipse.jdt.core.IJavaModelMarker; |
44 | 45 | import org.eclipse.jdt.core.IJavaModelStatusConstants; |
| 46 | +import org.eclipse.jdt.core.IJavaProject; |
45 | 47 | import org.eclipse.jdt.core.JavaCore; |
46 | 48 | import org.eclipse.jdt.core.JavaModelException; |
47 | 49 | import org.eclipse.jdt.core.compiler.CategorizedProblem; |
@@ -686,6 +688,11 @@ private int initializeBuilder(int kind, boolean forBuild) throws CoreException { |
686 | 688 | builtProjects = new LinkedHashSet<>(); |
687 | 689 | } |
688 | 690 | 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 | + } |
689 | 696 | } |
690 | 697 |
|
691 | 698 | this.binaryLocationsPerProject = new HashMap<>(3); |
@@ -878,6 +885,55 @@ private void recordNewState(State state) { |
878 | 885 | JavaModelManager.getJavaModelManager().setLastBuiltState(this.currentProject, state); |
879 | 886 | } |
880 | 887 |
|
| 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 | + |
881 | 937 | /** |
882 | 938 | * String representation for debugging purposes |
883 | 939 | */ |
|
0 commit comments