use of org.eclipse.xtext.resource.IResourceDescription.Delta in project xtext-core by eclipse.
the class DefaultResourceDescriptionManager method isAffected.
@Override
public boolean isAffected(Collection<Delta> deltas, IResourceDescription candidate, IResourceDescriptions context) {
Set<URI> outgoingReferences = descriptionUtils.collectOutgoingReferences(candidate);
if (!outgoingReferences.isEmpty()) {
for (IResourceDescription.Delta delta : deltas) if (hasChanges(delta, candidate) && outgoingReferences.contains(delta.getUri()))
return true;
}
// this is a tradeoff - we could either check whether a given delta uri is contained
// in a reachable container and check for intersecting names afterwards, or we can do
// the other way round
// unfortunately there is no way to decide reliably which algorithm scales better
// note that this method is called for each description so we have something like a
// number of deltas x number of resources which is not really nice
List<IContainer> containers = null;
Collection<QualifiedName> importedNames = getImportedNames(candidate);
if (!importedNames.isEmpty()) {
for (IResourceDescription.Delta delta : deltas) {
if (hasChanges(delta, candidate)) {
// not a java resource - delta's resource should be contained in a visible container
// as long as we did not delete the resource
URI uri = delta.getUri();
if ((uri.isPlatform() || uri.isArchive()) && delta.getNew() != null) {
if (containers == null)
containers = containerManager.getVisibleContainers(candidate, context);
boolean descriptionIsContained = false;
for (int i = 0; i < containers.size() && !descriptionIsContained; i++) {
descriptionIsContained = containers.get(i).hasResourceDescription(uri);
}
if (!descriptionIsContained) {
return isAffectedByExtensions(deltas, candidate, context);
}
}
if (isAffected(importedNames, delta.getNew()) || isAffected(importedNames, delta.getOld())) {
return true;
}
}
}
}
return isAffectedByExtensions(deltas, candidate, context);
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project xtext-eclipse by eclipse.
the class DirtyStateAwareResourceDescriptions method globalDescriptionsChanged.
public void globalDescriptionsChanged(IResourceDescription.Event event) {
ResourceDescriptionChangeEvent changeEvent = new ResourceDescriptionChangeEvent(Iterables.filter(event.getDeltas(), new Predicate<IResourceDescription.Delta>() {
@Override
public boolean apply(Delta input) {
URI uri = input.getUri();
return !dirtyStateManager.hasContent(uri);
}
}));
notifyListeners(changeEvent);
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project xtext-eclipse by eclipse.
the class ClusteringBuilderState method doUpdate.
/**
* Actually do the build.
*
* @param buildData
* the data that should be considered for the update
* @param newData
* the new resource descriptions as they are to be persisted (the new index after the build).
* Initially contains the old resource descriptions.
* @param monitor
* The progress monitor
* @return A list of deltas describing all changes made by the build.
*/
@Override
protected Collection<Delta> doUpdate(BuildData buildData, ResourceDescriptionsData newData, IProgressMonitor monitor) {
// We assume that we have 101 ticks to work with:
// 20 for writeNewResourceDescription
// 1 for queueAffectedResources
// 80 for updating and queueAffectedResources
// Within the mentioned 80 ticks we assume that 2/3 is spent for updating and 1/3 for queueAffectedResources
final SubMonitor progress = SubMonitor.convert(monitor, 101);
// Step 1: Clean the set of deleted URIs. If any of them are also added, they're not deleted.
final Set<URI> toBeDeleted = buildData.getAndRemoveToBeDeleted();
// Step 2: Create a new state (old state minus the deleted resources). This, by virtue of the flag
// NAMED_BUILDER_SCOPE in the resource set's load options
// and a Guice binding, is the index that is used during the build; i.e., linking during the build will
// use this. Once the build is completed, the persistable index is reset to the contents of newState by
// virtue of the newMap, which is maintained in synch with this.
ResourceSet resourceSet = buildData.getResourceSet();
final CurrentDescriptions newState = new CurrentDescriptions(resourceSet, newData, buildData);
buildData.getSourceLevelURICache().cacheAsSourceURIs(toBeDeleted);
installSourceLevelURIs(buildData);
// Step 3: Create a queue; write new temporary resource descriptions for the added or updated resources so that we can link
// subsequently; put all the added or updated resources into the queue.
writeNewResourceDescriptions(buildData, this, newState, progress.split(20));
if (progress.isCanceled()) {
throw new OperationCanceledException();
}
// in this set as potential candidates.
for (final URI uri : toBeDeleted) {
newData.removeDescription(uri);
}
final Set<URI> allRemainingURIs = Sets.newLinkedHashSet(newData.getAllURIs());
allRemainingURIs.removeAll(buildData.getToBeUpdated());
for (URI remainingURI : buildData.getAllRemainingURIs()) {
allRemainingURIs.remove(remainingURI);
}
// TODO: consider to remove any entry from upstream projects and independent projects
// from the set of remaining uris (template method or service?)
// this should reduce the number of to-be-checked descriptions significantly
// for common setups (large number of reasonable sized projects)
// Our return value. It contains all the deltas resulting from this build.
final Set<Delta> allDeltas = Sets.newHashSet();
// Step 5: Put all resources depending on a deleted resource into the queue. Also register the deltas in allDeltas.
if (!toBeDeleted.isEmpty()) {
for (final URI uri : toBeDeleted) {
final IResourceDescription oldDescription = this.getResourceDescription(uri);
if (oldDescription != null) {
allDeltas.add(new DefaultResourceDescriptionDelta(oldDescription, null));
}
}
}
// Add all pending deltas to all deltas (may be scheduled java deltas)
Collection<Delta> pendingDeltas = buildData.getAndRemovePendingDeltas();
allDeltas.addAll(pendingDeltas);
queueAffectedResources(allRemainingURIs, this, newState, allDeltas, allDeltas, buildData, progress.split(1));
installSourceLevelURIs(buildData);
IProject currentProject = getBuiltProject(buildData);
LoadOperation loadOperation = null;
try {
Queue<URI> queue = buildData.getURIQueue();
loadOperation = crossLinkingResourceLoader.create(resourceSet, currentProject);
loadOperation.load(queue);
// Step 6: Iteratively got through the queue. For each resource, create a new resource description and queue all depending
// resources that are not yet in the delta. Validate resources.
final SubMonitor subProgress = progress.split(80);
CancelIndicator cancelMonitor = new MonitorBasedCancelIndicator(progress);
while (!queue.isEmpty()) {
// heuristic: we multiply the size of the queue by 3 and spent 2 ticks for updating
// and 1 tick for queueAffectedResources since we assume that loading etc. is
// slower than queueAffectedResources.
subProgress.setWorkRemaining((queue.size() + 1) * 3);
int clusterIndex = 0;
final List<Delta> changedDeltas = Lists.newArrayList();
while (!queue.isEmpty()) {
if (subProgress.isCanceled()) {
loadOperation.cancel();
throw new OperationCanceledException();
}
if (!clusteringPolicy.continueProcessing(resourceSet, null, clusterIndex)) {
break;
}
URI changedURI = null;
URI actualResourceURI = null;
Resource resource = null;
Delta newDelta = null;
try {
// Load the resource and create a new resource description
LoadResult loadResult = loadOperation.next();
changedURI = loadResult.getUri();
actualResourceURI = loadResult.getResource().getURI();
resource = addResource(loadResult.getResource(), resourceSet);
subProgress.subTask("Updating resource " + resource.getURI().lastSegment());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Update resource description " + actualResourceURI);
}
queue.remove(changedURI);
if (toBeDeleted.contains(changedURI)) {
break;
}
buildLogger.log("indexing " + changedURI);
final IResourceDescription.Manager manager = getResourceDescriptionManager(actualResourceURI);
if (manager != null) {
// Resolve links here!
try {
EcoreUtil2.resolveLazyCrossReferences(resource, cancelMonitor);
final IResourceDescription description = manager.getResourceDescription(resource);
final IResourceDescription copiedDescription = BuilderStateUtil.create(description);
newDelta = manager.createDelta(this.getResourceDescription(actualResourceURI), copiedDescription);
} catch (OperationCanceledException e) {
loadOperation.cancel();
throw e;
} catch (WrappedException e) {
throw e;
} catch (RuntimeException e) {
LOGGER.error("Error resolving cross references on resource '" + actualResourceURI + "'", e);
throw new LoadOperationException(actualResourceURI, e);
}
}
} catch (final WrappedException ex) {
if (ex instanceof LoadOperationException) {
changedURI = ((LoadOperationException) ex).getUri();
}
Throwable cause = ex.getCause();
boolean wasResourceNotFound = false;
if (cause instanceof CoreException) {
if (IResourceStatus.RESOURCE_NOT_FOUND == ((CoreException) cause).getStatus().getCode()) {
wasResourceNotFound = true;
}
}
if (changedURI == null) {
// $NON-NLS-1$
LOGGER.error("Error loading resource", ex);
} else {
queue.remove(changedURI);
if (toBeDeleted.contains(changedURI))
break;
if (!wasResourceNotFound)
// $NON-NLS-1$
LOGGER.error("Error loading resource from: " + changedURI.toString(), ex);
if (resource != null) {
resourceSet.getResources().remove(resource);
}
final IResourceDescription oldDescription = this.getResourceDescription(changedURI);
final IResourceDescription newDesc = newState.getResourceDescription(changedURI);
ResourceDescriptionImpl indexReadyDescription = newDesc != null ? BuilderStateUtil.create(newDesc) : null;
if ((oldDescription != null || indexReadyDescription != null) && oldDescription != indexReadyDescription) {
newDelta = new DefaultResourceDescriptionDelta(oldDescription, indexReadyDescription);
}
}
}
if (newDelta != null) {
allDeltas.add(newDelta);
clusterIndex++;
if (newDelta.haveEObjectDescriptionsChanged())
changedDeltas.add(newDelta);
// Make the new resource description known and update the map.
newState.register(newDelta);
// Validate now.
if (!buildData.isIndexingOnly()) {
try {
updateMarkers(newDelta, resourceSet, subProgress);
} catch (OperationCanceledException e) {
loadOperation.cancel();
throw e;
} catch (Exception e) {
LOGGER.error("Error validating " + newDelta.getUri(), e);
}
}
}
// 2 ticks for updating since updating makes 2/3 of the work
subProgress.split(2);
}
loadOperation.cancel();
queueAffectedResources(allRemainingURIs, this, newState, changedDeltas, allDeltas, buildData, subProgress.split(1));
installSourceLevelURIs(buildData);
if (queue.size() > 0) {
loadOperation = crossLinkingResourceLoader.create(resourceSet, currentProject);
loadOperation.load(queue);
}
// Release memory
if (!queue.isEmpty() && !clusteringPolicy.continueProcessing(resourceSet, null, clusterIndex))
clearResourceSet(resourceSet);
}
} finally {
if (loadOperation != null)
loadOperation.cancel();
if (!progress.isCanceled())
progress.done();
}
return allDeltas;
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project xtext-eclipse by eclipse.
the class ParallelBuilderParticipant method doBuild.
@Override
protected void doBuild(List<Delta> deltas, Map<String, OutputConfiguration> outputConfigurations, Map<OutputConfiguration, Iterable<IMarker>> generatorMarkers, IBuildContext context, EclipseResourceFileSystemAccess2 access, IProgressMonitor progressMonitor) throws CoreException {
BlockingQueue<FileSystemAccessRequest> requestQueue = newBlockingQueue(QUEUE_CAPACITY);
// This queue is only used from the current thread
// thus there is no need for a blocking queue. The add operation should also not block the
// builder thread
Queue<ParallelBuildContext> afterGenerateQueue = new ArrayDeque<ParallelBuildContext>(QUEUE_CAPACITY);
FileSystemAccessQueue fileSystemAccessQueue = new FileSystemAccessQueue(requestQueue, progressMonitor);
Tripwire tripwire = new Tripwire();
EList<Adapter> adapters = context.getResourceSet().eAdapters();
EObservableAdapterList observableAdapters = (EObservableAdapterList) adapters;
adapters.add(fileSystemAccessQueue);
observableAdapters.addListener(tripwire);
try {
SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 1);
subMonitor.subTask("Compiling...");
access.setMonitor(subMonitor.split(1));
List<ListenableFuture<?>> tasks = Lists.newArrayList();
ListeningExecutorService executor = executors.getExecutor();
for (IResourceDescription.Delta delta : deltas) {
if (getResourceServiceProvider().canHandle(delta.getUri())) {
try {
ParallelBuildContext parallelBuildContext = new ParallelBuildContext(delta, context, outputConfigurations, generatorMarkers, fileSystemAccessQueue, afterGenerateQueue, access, progressMonitor);
Runnable runnable = createRunnable(parallelBuildContext);
tasks.add(executor.submit(runnable));
} catch (Exception e) {
addMarkerAndLogError(delta.getUri(), e);
}
}
}
ListenableFuture<List<Object>> generatorResult = Futures.successfulAsList(tasks);
List<SimpleEntry<URI, Throwable>> exceptions = Lists.newArrayList();
boolean interrupted = false;
try {
/*
* it is important to check generatorResult and requestQueue second
* as it can happen that if you use !requestQueue.isEmpty() || !generatorResult.isDone()
* that the generatorResult.isDone() becomes true after requestQueue.isEmpty() was checked
* and thus requestQueue.isEmpty() changes back to false
* but we stop the while loop anyway and thus miss generated files.
*/
while (!generatorResult.isDone() || !requestQueue.isEmpty()) {
if (subMonitor.isCanceled()) {
cancelProcessing(requestQueue, afterGenerateQueue, generatorResult);
throw new OperationCanceledException();
}
FileSystemAccessRequest request = null;
try {
request = requestQueue.poll(QUEUE_POLL_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
interrupted = true;
}
if (request != null) {
try {
request.run();
} catch (OperationCanceledException e) {
cancelProcessing(requestQueue, afterGenerateQueue, generatorResult);
throw e;
} catch (Exception e) {
Throwable cause = e;
if (cause instanceof CoreException) {
cause = cause.getCause();
}
exceptions.add(new SimpleEntry<URI, Throwable>(request.getUri(), cause));
}
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
for (SimpleEntry<URI, Throwable> exception : exceptions) {
addMarkerAndLogError(exception.getKey(), exception.getValue());
}
}
} finally {
observableAdapters.removeListener(tripwire);
adapters.remove(fileSystemAccessQueue);
}
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project xtext-eclipse by eclipse.
the class XtextBuilder method doClean.
/**
* @param toBeBuilt the collected URIs that should be handled by this clean operation.
* @param removedProjects additional projects that were available but do no longer have the Xtext nature or have been deleted
*
* @param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
* to call done() on the given monitor. Accepts null, indicating that no progress should be
* reported and that the operation cannot be cancelled.
*/
protected void doClean(ToBeBuilt toBeBuilt, Set<String> removedProjects, IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 2);
SetWithProjectNames toBeDeletedAndProjects = new SetWithProjectNames(toBeBuilt.getToBeDeleted(), getProject().getName(), removedProjects);
ImmutableList<Delta> deltas = builderState.clean(toBeDeletedAndProjects, progress.split(1));
if (participant != null) {
Set<URI> sourceURIs = new SourceLevelURICache().getSourcesFrom(toBeBuilt.getToBeDeleted(), resourceServiceProvideRegistry);
participant.build(new BuildContext(this, getResourceSetProvider().get(getProject()), deltas, sourceURIs, BuildType.CLEAN), progress.split(1));
} else {
progress.worked(1);
}
}
Aggregations