/******************************************************************************* * Copyright © 2012, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.ide.core.internal.generation; import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.edt.compiler.internal.core.builder.BuildException; import org.eclipse.edt.compiler.internal.core.builder.CancelledException; import org.eclipse.edt.compiler.internal.core.builder.IBuildNotifier; import org.eclipse.edt.compiler.internal.core.builder.NullBuildNotifier; import org.eclipse.edt.ide.core.CoreIDEPluginStrings; import org.eclipse.edt.ide.core.EDTCoreIDEPlugin; import org.eclipse.edt.ide.core.internal.builder.AbstractMarkerProblemRequestor; import org.eclipse.edt.ide.core.internal.builder.BuildManager; import org.eclipse.edt.ide.core.internal.builder.BuildNotifier; import org.eclipse.edt.ide.core.internal.lookup.ProjectBuildPathManager; import org.eclipse.edt.ide.core.utils.ProjectSettingsUtility; //TODO: // should we generate binary projects? /** * Builder that runs generation on compiled EGL parts. */ public class GenerationBuilder extends IncrementalProjectBuilder { @Override protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { IBuildNotifier notifier; if (monitor == null) { notifier = NullBuildNotifier.getInstance(); } else { notifier = new BuildNotifier(monitor); } boolean isOK = false; IResourceDelta delta = getDelta(getProject()); notifier.begin(); try { if(isWorthBuilding()){ if (kind == IncrementalProjectBuilder.FULL_BUILD) { doClean(); cleanBuild(delta, notifier); } else if (!GenerationBuildManager.getInstance().getProjectState(getProject())) { doClean(); cleanBuild(null, notifier); } else if (needFullBuild()) { doClean(); cleanBuild(null, notifier); } else { if (delta == null) { doClean(); cleanBuild(delta, notifier); } else{ incrementalBuild(delta, notifier); } } isOK = true; } } catch (CancelledException canceledException) { throw new OperationCanceledException(); } finally { if (!isOK) { GenerationBuildManager.getInstance().setProjectState(getProject(), false); } else { GenerationBuildManager.getInstance().putProject( getProject(), // only store the default gen IDs if they're being used for this project ProjectSettingsUtility.getCompilerId(getProject()) == null ? ProjectSettingsUtility.getWorkspaceGeneratorIds() : null); } notifier.done(); } return null; } protected void clean(IProgressMonitor monitor) { try { doClean(); } catch (Exception e) { EDTCoreIDEPlugin.getPlugin().log("EDT Generation Clean Failure",e); //$NON-NLS-1$ GenerationBuildManager.getInstance().clear(getProject()); } } protected boolean cleanBuild(IResourceDelta delta, IBuildNotifier notifier) { GenerationBuildManager.getInstance().setProjectState(getProject(), false); CleanGenerator gen = new CleanGenerator(this, notifier); return gen.build(delta); } protected boolean incrementalBuild(IResourceDelta delta, IBuildNotifier notifier) { GenerationBuildManager.getInstance().setProjectState(getProject(), false); IncrementalGenerator gen = new IncrementalGenerator(this, notifier); return gen.build(delta); } protected void doClean() { GenerationBuildManager.getInstance().clear(getProject()); deleteAllMarkers(); //TODO What else should be done here? Tell the generators to "clean up" their generated artifacts? } protected void deleteAllMarkers() { try { getProject().deleteMarkers(EDTCoreIDEPlugin.GENERATION_PROBLEM, true, IResource.DEPTH_INFINITE); } catch (CoreException e) { throw new BuildException(e); } } private boolean needFullBuild() { if (ProjectSettingsUtility.getCompilerId(getProject()) == null) { // When using the workspace settings, regenerate everything if the default generators changed. String[] oldIds = GenerationBuildManager.getInstance().getDefaultGenIDs(getProject()); // When using the workspace settings, regenerate everything we previously weren't using the workspace settings. if (oldIds == null) { return true; } // When using the workspace settings, regenerate everything if the default generators changed. String[] currIds = ProjectSettingsUtility.getWorkspaceGeneratorIds(); if (currIds.length != oldIds.length) { return true; } for (String curr : currIds) { boolean foundMatch = false; for (String old : oldIds) { if (curr.equals(old)) { foundMatch = true; break; } } if (!foundMatch) { return true; } } } else { if (GenerationBuildManager.getInstance().getDefaultGenIDs(getProject()) != null) { // When using project-specific settings, regenerate everything if we previously used the workspace settings. return true; } } return false; } private boolean isWorthBuilding() { try { // Check to see if this project has any unhandled build exceptions if(projectHasUnhandledBuildException(getProject())){ // Remove all existing generation problem markers, since we are about to issue a single problem marker for the entire project getProject().deleteMarkers(EDTCoreIDEPlugin.GENERATION_PROBLEM, true, IResource.DEPTH_INFINITE); // Indicate that the project could not be generated IMarker marker = getProject().createMarker(EDTCoreIDEPlugin.GENERATION_PROBLEM); marker.setAttribute(IMarker.MESSAGE, CoreIDEPluginStrings.projectHasBuildProblem); marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); return false; } // make sure all of the prereq projects do not have an unhandled EDT build exception IProject currentProject = getProject(); IProject[] requiredProjects = ProjectBuildPathManager.getInstance().getProjectBuildPath(getProject()).getRequiredProjects(); for (int i = 0; i < requiredProjects.length; i++) { IProject p = requiredProjects[i]; // We have to confirm that a project exists and is open before we try to get its state. // We won't get to this point if the project has an unhandled EDT build exception due to the marker check above if (p.exists() && p.isOpen()){ if(!BuildManager.getInstance().getProjectState(p)) { currentProject.deleteMarkers(EDTCoreIDEPlugin.GENERATION_PROBLEM, true, IResource.DEPTH_INFINITE); IMarker marker = currentProject.createMarker(EDTCoreIDEPlugin.GENERATION_PROBLEM); marker.setAttribute(IMarker.MESSAGE, projectHasUnhandledBuildException(p) ? CoreIDEPluginStrings.bind(CoreIDEPluginStrings.prereqProjectHasBuildProblem, p.getName()) : CoreIDEPluginStrings.bind(CoreIDEPluginStrings.prereqProjectMustBeRebuilt, p.getName())); marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); return false; } } } } catch (CoreException e) { throw new BuildException(e); } return true; } private boolean projectHasUnhandledBuildException(IProject project) throws CoreException{ IMarker[] markers = project.findMarkers(AbstractMarkerProblemRequestor.BUILD_PROBLEM, false, IResource.DEPTH_ZERO); if(markers.length > 0){ return true; } return false; } }