@Override public void build(final IBuildContext context, IProgressMonitor monitor) throws CoreException { if (!isEnabled(context)) { return; } final List<IResourceDescription.Delta> deltas = getRelevantDeltas(context); if (deltas.isEmpty()) { return; } StoppedTask task = Stopwatches.forTask( "org.eclipse.xtext.builder.BuilderParticipant.build(IBuildContext, IProgressMonitor)"); try { task.start(); // monitor handling if (monitor.isCanceled()) throw new OperationCanceledException(); SubMonitor subMonitor = SubMonitor.convert(monitor, context.getBuildType() == BuildType.RECOVERY ? 5 : 3); EclipseResourceFileSystemAccess2 access = fileSystemAccessProvider.get(); IProject builtProject = context.getBuiltProject(); access.setProject(builtProject); Map<String, OutputConfiguration> outputConfigurations = getOutputConfigurations(context); refreshOutputFolders(context, outputConfigurations, subMonitor.newChild(1)); if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } access.setOutputConfigurations(outputConfigurations); if (context.getBuildType() == BuildType.CLEAN || context.getBuildType() == BuildType.RECOVERY) { SubMonitor cleanMonitor = SubMonitor.convert(subMonitor.newChild(2), outputConfigurations.size()); for (OutputConfiguration config : outputConfigurations.values()) { cleanOutput(context, config, access, cleanMonitor.newChild(1)); } if (context.getBuildType() == BuildType.CLEAN) return; } Map<OutputConfiguration, Iterable<IMarker>> generatorMarkers = getGeneratorMarkers(builtProject, outputConfigurations.values()); if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } doBuild( deltas, outputConfigurations, generatorMarkers, context, access, subMonitor.newChild(2)); } finally { task.stop(); } }
/** @since 2.7 */ protected void doBuild( List<IResourceDescription.Delta> deltas, Map<String, OutputConfiguration> outputConfigurations, Map<OutputConfiguration, Iterable<IMarker>> generatorMarkers, IBuildContext context, EclipseResourceFileSystemAccess2 access, IProgressMonitor progressMonitor) throws CoreException { final int numberOfDeltas = deltas.size(); SubMonitor subMonitor = SubMonitor.convert(progressMonitor, numberOfDeltas / MONITOR_CHUNK_SIZE + 1); SubMonitor currentMonitor = null; int clusterIndex = 0; for (int i = 0; i < numberOfDeltas; i++) { IResourceDescription.Delta delta = deltas.get(i); if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } if (i % 10 == 0) { subMonitor.subTask( "Compiling chunk " + (i / MONITOR_CHUNK_SIZE + 1) + " of " + (numberOfDeltas / MONITOR_CHUNK_SIZE + 1)); currentMonitor = subMonitor.newChild(1); access.setMonitor(currentMonitor); } if (logger.isDebugEnabled()) { logger.debug("Compiling " + delta.getUri() + " (" + i + " of " + numberOfDeltas + ")"); } if (delta.getNew() != null && !clusteringPolicy.continueProcessing( context.getResourceSet(), delta.getUri(), clusterIndex)) { clearResourceSet(context.getResourceSet()); clusterIndex = 0; } Set<IFile> derivedResources = getDerivedResources(delta, outputConfigurations, generatorMarkers); access.setPostProcessor(getPostProcessor(delta, context, derivedResources)); if (doGenerate(delta, context, access)) { clusterIndex++; access.flushSourceTraces(); } cleanDerivedResources(delta, derivedResources, context, access, currentMonitor); } }
/** @since 2.3 */ protected List<IResourceDescription.Delta> getRelevantDeltas(IBuildContext context) { List<IResourceDescription.Delta> result = newArrayList(); for (IResourceDescription.Delta delta : context.getDeltas()) { if (resourceServiceProvider.canHandle(delta.getUri())) result.add(delta); } return result; }
protected Map<String, OutputConfiguration> getOutputConfigurations(IBuildContext context) { Set<OutputConfiguration> configurations = outputConfigurationProvider.getOutputConfigurations(context.getBuiltProject()); return uniqueIndex( configurations, new Function<OutputConfiguration, String>() { public String apply(OutputConfiguration from) { return from.getName(); } }); }
/** @since 2.3 */ protected List<IResourceDescription.Delta> getRelevantDeltas(IBuildContext context) { List<IResourceDescription.Delta> result = newArrayList(); for (IResourceDescription.Delta delta : context.getDeltas()) { if (resourceServiceProvider.canHandle(delta.getUri()) && (resourceServiceProvider instanceof IResourceServiceProviderExtension) && !((IResourceServiceProviderExtension) resourceServiceProvider) .isReadOnly(delta.getUri())) { result.add(delta); } } return result; }
protected void refreshOutputFolders( IBuildContext ctx, Map<String, OutputConfiguration> outputConfigurations, IProgressMonitor monitor) throws CoreException { SubMonitor subMonitor = SubMonitor.convert(monitor, outputConfigurations.size()); for (OutputConfiguration config : outputConfigurations.values()) { SubMonitor child = subMonitor.newChild(1); final IProject project = ctx.getBuiltProject(); IFolder folder = project.getFolder(config.getOutputDirectory()); folder.refreshLocal(IResource.DEPTH_INFINITE, child); } }
protected void handleChangedContents( Delta delta, IBuildContext context, EclipseResourceFileSystemAccess2 fileSystemAccess) throws CoreException { // TODO: we will run out of memory here if the number of deltas is large enough Resource resource = context.getResourceSet().getResource(delta.getUri(), true); if (shouldGenerate(resource, context)) { try { generator.doGenerate(resource, fileSystemAccess); } catch (RuntimeException e) { if (e.getCause() instanceof CoreException) { throw (CoreException) e.getCause(); } throw e; } } }
protected boolean shouldGenerate(Resource resource, IBuildContext context) { try { Iterable<Pair<IStorage, IProject>> storages = storage2UriMapper.getStorages(resource.getURI()); for (Pair<IStorage, IProject> pair : storages) { if (pair.getFirst() instanceof IFile && pair.getSecond().equals(context.getBuiltProject())) { IFile file = (IFile) pair.getFirst(); return file.findMaxProblemSeverity(null, true, IResource.DEPTH_INFINITE) != IMarker.SEVERITY_ERROR; } } return false; } catch (CoreException exc) { throw new WrappedException(exc); } }
protected void cleanOutput( IBuildContext ctx, OutputConfiguration config, IProgressMonitor monitor) throws CoreException { final IProject project = ctx.getBuiltProject(); IFolder folder = project.getFolder(config.getOutputDirectory()); if (!folder.exists()) return; if (config.isCanClearOutputDirectory()) { for (IResource resource : folder.members()) resource.delete(IResource.KEEP_HISTORY, monitor); } else { if (config.isCleanUpDerivedResources()) { List<IFile> resources = derivedResourceMarkers.findDerivedResources(folder, null); for (IFile iFile : resources) { iFile.delete(IResource.KEEP_HISTORY, monitor); } } } }
protected void refreshOutputFolders( IBuildContext ctx, Map<String, OutputConfiguration> outputConfigurations, IProgressMonitor monitor) throws CoreException { SubMonitor subMonitor = SubMonitor.convert(monitor, outputConfigurations.size()); for (OutputConfiguration config : outputConfigurations.values()) { SubMonitor child = subMonitor.newChild(1); final IProject project = ctx.getBuiltProject(); for (IContainer container : getOutputs(project, config)) { if (monitor.isCanceled()) { throw new OperationCanceledException(); } container.refreshLocal(IResource.DEPTH_INFINITE, child); } } }
/** @since 2.7 */ protected void cleanDerivedResources( Delta delta, Set<IFile> derivedResources, IBuildContext context, EclipseResourceFileSystemAccess2 access, IProgressMonitor deleteMonitor) throws CoreException { String uri = delta.getUri().toString(); for (IFile iFile : newLinkedHashSet(derivedResources)) { if (deleteMonitor.isCanceled()) { throw new OperationCanceledException(); } IMarker marker = derivedResourceMarkers.findDerivedResourceMarker(iFile, uri); if (marker != null) marker.delete(); if (derivedResourceMarkers.findDerivedResourceMarkers(iFile).length == 0) { access.deleteFile(iFile, deleteMonitor); context.needRebuild(); } } }
/** @since 2.5 */ protected void cleanOutput( IBuildContext ctx, OutputConfiguration config, EclipseResourceFileSystemAccess2 access, IProgressMonitor monitor) throws CoreException { final IProject project = ctx.getBuiltProject(); for (IContainer container : getOutputs(project, config)) { if (!container.exists()) { return; } if (config.isCanClearOutputDirectory()) { for (IResource resource : container.members()) { if (!config.isKeepLocalHistory()) { resource.delete(IResource.NONE, monitor); } else if (access == null) { resource.delete(IResource.KEEP_HISTORY, monitor); } else { delete(resource, config, access, monitor); } } } else if (config.isCleanUpDerivedResources()) { List<IFile> resources = derivedResourceMarkers.findDerivedResources(container, null); for (IFile iFile : resources) { if (monitor.isCanceled()) { throw new OperationCanceledException(); } if (access != null) { access.deleteFile(iFile, config.getName(), monitor); } else { iFile.delete( config.isKeepLocalHistory() ? IResource.KEEP_HISTORY : IResource.NONE, monitor); } } } } }
public void build(final IBuildContext context, IProgressMonitor monitor) throws CoreException { if (!isEnabled(context)) { return; } final List<IResourceDescription.Delta> deltas = getRelevantDeltas(context); if (deltas.isEmpty()) { return; } final int numberOfDeltas = deltas.size(); // monitor handling if (monitor.isCanceled()) throw new OperationCanceledException(); SubMonitor subMonitor = SubMonitor.convert(monitor, numberOfDeltas + 3); EclipseResourceFileSystemAccess2 access = fileSystemAccessProvider.get(); final IProject builtProject = context.getBuiltProject(); access.setProject(builtProject); final Map<String, OutputConfiguration> outputConfigurations = getOutputConfigurations(context); refreshOutputFolders(context, outputConfigurations, subMonitor.newChild(1)); access.setOutputConfigurations(outputConfigurations); if (context.getBuildType() == BuildType.CLEAN || context.getBuildType() == BuildType.RECOVERY) { SubMonitor cleanMonitor = SubMonitor.convert(subMonitor.newChild(1), outputConfigurations.size()); for (OutputConfiguration config : outputConfigurations.values()) { cleanOutput(context, config, cleanMonitor.newChild(1)); } if (context.getBuildType() == BuildType.CLEAN) return; } Map<OutputConfiguration, Iterable<IMarker>> generatorMarkers = newHashMap(); for (OutputConfiguration config : outputConfigurations.values()) { if (config.isCleanUpDerivedResources()) { final IFolder outputFolder = builtProject.getFolder(config.getOutputDirectory()); final Iterable<IMarker> markers = derivedResourceMarkers.findDerivedResourceMarkers( outputFolder, generatorIdProvider.getGeneratorIdentifier()); generatorMarkers.put(config, markers); } } for (int i = 0; i < numberOfDeltas; i++) { final IResourceDescription.Delta delta = deltas.get(i); // monitor handling if (subMonitor.isCanceled()) throw new OperationCanceledException(); subMonitor.subTask( "Compiling " + delta.getUri().lastSegment() + " (" + i + " of " + numberOfDeltas + ")"); access.setMonitor(subMonitor.newChild(1)); final String uri = delta.getUri().toString(); final Set<IFile> derivedResources = newLinkedHashSet(); for (OutputConfiguration config : outputConfigurations.values()) { if (config.isCleanUpDerivedResources()) { Iterable<IMarker> markers = generatorMarkers.get(config); for (IMarker marker : markers) { String source = derivedResourceMarkers.getSource(marker); if (source != null && source.equals(uri)) derivedResources.add((IFile) marker.getResource()); } } } access.setPostProcessor( new EclipseResourceFileSystemAccess2.IFileCallback() { public boolean beforeFileDeletion(IFile file) { derivedResources.remove(file); context.needRebuild(); return true; } public void afterFileUpdate(IFile file) { handleFileAccess(file); } public void afterFileCreation(IFile file) { handleFileAccess(file); } protected void handleFileAccess(IFile file) { try { derivedResources.remove(file); derivedResourceMarkers.installMarker(file, uri); context.needRebuild(); } catch (CoreException e) { throw new RuntimeException(e); } } }); if (delta.getNew() != null) { handleChangedContents(delta, context, access); } access.flushSourceTraces(); SubMonitor deleteMonitor = SubMonitor.convert(subMonitor.newChild(1), derivedResources.size()); for (IFile iFile : newLinkedHashSet(derivedResources)) { IMarker marker = derivedResourceMarkers.findDerivedResourceMarker(iFile, uri); if (marker != null) marker.delete(); if (derivedResourceMarkers.findDerivedResourceMarkers(iFile).length == 0) { access.deleteFile(iFile, deleteMonitor); context.needRebuild(); } } } }
protected boolean isEnabled(final IBuildContext context) { return builderPreferenceAccess.isAutoBuildEnabled(context.getBuiltProject()); }