use of org.eclipse.xtext.resource.IResourceDescription.Delta in project dsl-devkit by dsldevkit.
the class MonitoredClusteringBuilderState method updateDeltas.
/**
* Updates the markers on a collection of resource.
*
* @param deltas
* for the changed resources
* @param resourceSet
* containing the resource
* @param monitor
* to report progress
*/
protected void updateDeltas(final Collection<Delta> deltas, final ResourceSet resourceSet, final IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, deltas.size() * 2);
for (Delta delta : deltas) {
checkForCancellation(monitor);
updateMarkers(delta, resourceSet, progress.newChild(1));
postProcess(delta, resourceSet, progress.newChild(1));
}
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project dsl-devkit by dsldevkit.
the class MonitoredClusteringBuilderState method doUpdate.
/**
* {@inheritDoc}
*/
@Override
protected // CHECKSTYLE:CHECK-OFF NestedTryDepth
Collection<Delta> doUpdate(final BuildData buildData, final ResourceDescriptionsData newData, final IProgressMonitor monitor) {
// NOPMD
final SubMonitor progress = SubMonitor.convert(monitor, 100);
// Step 1: Clean the set of deleted URIs. If any of them are also added, they're not deleted.
final Set<URI> toBeDeleted = Sets.newHashSet(buildData.getToBeDeleted());
toBeDeleted.removeAll(buildData.getToBeUpdated());
ResourceSet resourceSet = buildData.getResourceSet();
// Step 2: Create a new state (old state minus the deleted resources). This, by virtue of the flag above
// 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.
final CurrentDescriptions2 newState = createCurrentDescriptions(resourceSet, newData);
final Map<URI, IResourceDescription> oldDescriptions = saveOldDescriptions(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.
// CHECKSTYLE:CONSTANTS-OFF
writeNewResourceDescriptions(buildData, this, newState, newData, progress.newChild(20));
// CHECKSTYLE:CONSTANTS-ON
// clear resource set to wipe out derived state of phase 1 model inference and all corresponding references
clearResourceSet(resourceSet);
LOGGER.info(Messages.MonitoredClusteringBuilderState_PHASE_ONE_DONE);
checkForCancellation(progress);
// in this set as potential candidates. Make sure that notInDelta is a modifiable Set, not some immutable view.
for (final URI uri : toBeDeleted) {
checkForCancellation(monitor);
newData.removeDescription(uri);
}
final Set<URI> allRemainingURIs = createCandidateSet(newData.getAllURIs());
allRemainingURIs.removeAll(buildData.getToBeUpdated());
for (URI remainingURI : buildData.getAllRemainingURIs()) {
allRemainingURIs.remove(remainingURI);
}
flushChanges(newData);
// 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()) {
addDeletedURIsToDeltas(toBeDeleted, allDeltas, oldDescriptions);
// Here, we have only the deltas for deleted resources in allDeltas. Make sure that all markers are removed.
// Normally, resources in toBeDeleted will have their storage(s) deleted, so Eclipse will automatically
// remove the markers. However, if the ToBeBuiltComputer adds resources to the tobeDeleted set that are not or
// have not been physically removed, markers would otherwise remain even though the resource is no longer part
// of the Xtext world (index). Since the introduction of IResourcePostProcessor, we also need to do this to give
// the post-processor a chance to do whatever needs doing when a resource is removed.
updateDeltas(allDeltas, resourceSet, progress.newChild(1));
}
// 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.newChild(1));
IProject currentProject = getBuiltProject(buildData);
IResourceLoader.LoadOperation loadOperation = null;
final BuilderWatchdog watchdog = new BuilderWatchdog();
try {
traceSet.started(BuildLinkingEvent.class);
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. Do this in chunks.
final SubMonitor subProgress = progress.newChild(80);
final CancelIndicator cancelMonitor = new CancelIndicator() {
@Override
public boolean isCanceled() {
return subProgress.isCanceled();
}
};
watchdog.start();
int index = 1;
while (!queue.isEmpty()) {
// CHECKSTYLE:CONSTANTS-OFF
subProgress.setWorkRemaining(queue.size() * 3);
// CHECKSTYLE:CONSTANTS-ON
final List<Delta> newDeltas = Lists.newArrayListWithExpectedSize(clusterSize);
final List<Delta> changedDeltas = Lists.newArrayListWithExpectedSize(clusterSize);
while (!queue.isEmpty() && loadingStrategy.mayProcessAnotherResource(resourceSet, newDeltas.size())) {
if (subProgress.isCanceled() || !loadOperation.hasNext()) {
if (!loadOperation.hasNext()) {
LOGGER.warn(Messages.MonitoredClusteringBuilderState_NO_MORE_RESOURCES);
}
loadOperation.cancel();
throw new OperationCanceledException();
}
// Load the resource and create a new resource description
URI changedURI = null;
Resource resource = null;
Delta newDelta = null;
final long initialMemory = Runtime.getRuntime().freeMemory();
final int initialResourceSetSize = resourceSet.getResources().size();
final long initialTime = System.nanoTime();
try {
// Load the resource and create a new resource description
resource = addResource(loadOperation.next().getResource(), resourceSet);
changedURI = resource.getURI();
traceSet.started(ResourceProcessingEvent.class, changedURI);
queue.remove(changedURI);
if (toBeDeleted.contains(changedURI)) {
break;
}
watchdog.reportWorkStarted(changedURI);
traceSet.started(ResourceLinkingEvent.class, changedURI);
final IResourceDescription.Manager manager = getResourceDescriptionManager(changedURI);
if (manager != null) {
final Object[] bindings = { Integer.valueOf(index), Integer.valueOf(index + queue.size()), URI.decode(resource.getURI().lastSegment()) };
subProgress.subTask(NLS.bind(Messages.MonitoredClusteringBuilderState_UPDATE_DESCRIPTIONS, bindings));
// Resolve links here!
try {
EcoreUtil2.resolveLazyCrossReferences(resource, cancelMonitor);
final IResourceDescription description = manager.getResourceDescription(resource);
final IResourceDescription copiedDescription = descriptionCopier.copy(description);
newDelta = manager.createDelta(getSavedResourceDescription(oldDescriptions, changedURI), copiedDescription);
} catch (StackOverflowError ex) {
queue.remove(changedURI);
logStackOverflowErrorStackTrace(ex, changedURI);
}
}
// CHECKSTYLE:CHECK-OFF IllegalCatch - guard against ill behaved implementations
} catch (final Exception ex) {
// CHECKSTYLE:CHECK-ON IllegalCatch
pollForCancellation(monitor);
if (ex instanceof LoadOperationException) {
// NOPMD
LoadOperationException loadException = (LoadOperationException) ex;
if (loadException.getCause() instanceof TimeoutException) {
// Load request timed out, URI of the resource is not available
String message = loadException.getCause().getMessage();
LOGGER.warn(message);
} else {
// Exception when loading resource, URI should be available
changedURI = ((LoadOperationException) ex).getUri();
LOGGER.error(NLS.bind(Messages.MonitoredClusteringBuilderState_CANNOT_LOAD_RESOURCE, changedURI), ex);
}
} else {
LOGGER.error(NLS.bind(Messages.MonitoredClusteringBuilderState_CANNOT_LOAD_RESOURCE, changedURI), ex);
}
if (changedURI != null) {
queue.remove(changedURI);
}
if (resource != null) {
resourceSet.getResources().remove(resource);
}
final IResourceDescription oldDescription = getSavedResourceDescription(oldDescriptions, changedURI);
if (oldDescription != null) {
newDelta = new DefaultResourceDescriptionDelta(oldDescription, null);
}
} finally {
traceSet.ended(ResourceLinkingEvent.class);
}
if (newDelta != null) {
allDeltas.add(newDelta);
if (newDelta.haveEObjectDescriptionsChanged()) {
changedDeltas.add(newDelta);
}
if (recordDeltaAsNew(newDelta)) {
newDeltas.add(newDelta);
// Make the new resource description known in the new index.
newState.register(newDelta);
}
try {
// Validate directly, instead of bulk validating after the cluster.
updateMarkers(newDelta, resourceSet, subProgress.newChild(1, SubMonitor.SUPPRESS_ALL_LABELS));
postProcess(newDelta, resourceSet, subProgress.newChild(1));
} catch (StackOverflowError ex) {
queue.remove(changedURI);
logStackOverflowErrorStackTrace(ex, changedURI);
}
} else {
subProgress.worked(2);
}
if (changedURI != null) {
final long memoryDelta = Runtime.getRuntime().freeMemory() - initialMemory;
final int resourceSetSizeDelta = resourceSet.getResources().size() - initialResourceSetSize;
final long timeDelta = System.nanoTime() - initialTime;
traceSet.trace(ResourceLinkingMemoryEvent.class, changedURI, memoryDelta, resourceSetSizeDelta, timeDelta);
watchdog.reportWorkEnded(index, index + queue.size());
}
// Clear caches of resource
if (resource instanceof XtextResource) {
((XtextResource) resource).getCache().clear(resource);
}
traceSet.ended(ResourceProcessingEvent.class);
buildData.getSourceLevelURICache().getSources().remove(changedURI);
subProgress.worked(1);
index++;
}
loadOperation.cancel();
queueAffectedResources(allRemainingURIs, this, newState, changedDeltas, allDeltas, buildData, subProgress.newChild(1));
newDeltas.clear();
changedDeltas.clear();
if (queue.size() > 0) {
loadOperation = crossLinkingResourceLoader.create(resourceSet, currentProject);
loadOperation.load(queue);
}
if (!queue.isEmpty()) {
traceSet.trace(ClusterClosedEvent.class, Long.valueOf(resourceSet.getResources().size()));
clearResourceSet(resourceSet);
}
// TODO flush required here or elsewhere ?
// flushChanges(newData);
}
} finally {
// Report the current size of the resource set
traceSet.trace(ClusterClosedEvent.class, Long.valueOf(resourceSet.getResources().size()));
if (loadOperation != null) {
loadOperation.cancel();
}
traceSet.ended(BuildLinkingEvent.class);
watchdog.interrupt();
}
return allDeltas;
// CHECKSTYLE:CHECK-ON NestedTryDepth
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project dsl-devkit by dsldevkit.
the class MonitoredClusteringBuilderState method writeResources.
/**
* Writes a list of resources into the index given their {@link URI}s.
*
* @param toWrite
* The {@link URI} of the resources to write
* @param buildData
* The underlying data for the write operation.
* @param oldState
* The old index
* @param newState
* The new index
* @param monitor
* The progress monitor used for user feedback
* @return a List with the list of loaded resources {@link URI} in the first position and a list of {@link URI}s of resources that could not be loaded in the
* second position.
*/
@SuppressWarnings("unchecked")
private List<List<URI>> writeResources(final Collection<URI> toWrite, final BuildData buildData, final IResourceDescriptions oldState, final CurrentDescriptions newState, final IProgressMonitor monitor) {
ResourceSet resourceSet = buildData.getResourceSet();
IProject currentProject = getBuiltProject(buildData);
List<URI> toBuild = Lists.newLinkedList();
List<URI> toRetry = Lists.newLinkedList();
IResourceLoader.LoadOperation loadOperation = null;
try {
int resourcesToWriteSize = toWrite.size();
int index = 1;
loadOperation = globalIndexResourceLoader.create(resourceSet, currentProject);
loadOperation.load(toWrite);
// large resources and "scarce" memory (say, about 500MB).
while (loadOperation.hasNext()) {
if (monitor.isCanceled()) {
loadOperation.cancel();
throw new OperationCanceledException();
}
URI uri = null;
Resource resource = null;
try {
resource = addResource(loadOperation.next().getResource(), resourceSet);
uri = resource.getURI();
final Object[] bindings = { Integer.valueOf(index), Integer.valueOf(resourcesToWriteSize), uri.fileExtension(), URI.decode(uri.lastSegment()) };
monitor.subTask(NLS.bind(Messages.MonitoredClusteringBuilderState_WRITE_ONE_DESCRIPTION, bindings));
traceSet.started(ResourceIndexingEvent.class, uri);
final IResourceDescription.Manager manager = getResourceDescriptionManager(uri);
if (manager != null) {
final IResourceDescription description = manager.getResourceDescription(resource);
// We don't care here about links, we really just want the exported objects so that we can link in the next phase.
// Set flag to make unresolvable cross-references raise an error
resourceSet.getLoadOptions().put(ILazyLinkingResource2.MARK_UNRESOLVABLE_XREFS, Boolean.FALSE);
final IResourceDescription copiedDescription = new FixedCopiedResourceDescription(description);
final boolean hasUnresolvedLinks = resourceSet.getLoadOptions().get(ILazyLinkingResource2.MARK_UNRESOLVABLE_XREFS) == Boolean.TRUE;
if (hasUnresolvedLinks) {
toRetry.add(uri);
resourceSet.getResources().remove(resource);
} else {
final Delta intermediateDelta = manager.createDelta(oldState.getResourceDescription(uri), copiedDescription);
newState.register(intermediateDelta);
toBuild.add(uri);
}
}
} catch (final WrappedException ex) {
pollForCancellation(monitor);
if (uri == null && ex instanceof LoadOperationException) {
// NOPMD
uri = ((LoadOperationException) ex).getUri();
}
LOGGER.error(NLS.bind(Messages.MonitoredClusteringBuilderState_CANNOT_LOAD_RESOURCE, uri), ex);
if (resource != null) {
resourceSet.getResources().remove(resource);
}
if (uri != null) {
final IResourceDescription oldDescription = oldState.getResourceDescription(uri);
if (oldDescription != null) {
newState.register(new DefaultResourceDescriptionDelta(oldDescription, null));
}
}
// CHECKSTYLE:CHECK-OFF IllegalCatch
// If we couldn't load it, there's no use trying again: do not add it to the queue
} catch (final Throwable e) {
// unfortunately the parser sometimes crashes (yet unreported Xtext bug)
// CHECKSTYLE:CHECK-ON IllegalCatch
pollForCancellation(monitor);
LOGGER.error(NLS.bind(Messages.MonitoredClusteringBuilderState_CANNOT_LOAD_RESOURCE, uri), e);
if (resource != null) {
resourceSet.getResources().remove(resource);
}
} finally {
// Clear caches of resource
if (resource instanceof XtextResource) {
((XtextResource) resource).getCache().clear(resource);
}
traceSet.ended(ResourceIndexingEvent.class);
monitor.worked(1);
}
if (!loadingStrategy.mayProcessAnotherResource(resourceSet, resourceSet.getResources().size())) {
clearResourceSet(resourceSet);
}
index++;
}
} finally {
if (loadOperation != null) {
loadOperation.cancel();
}
}
return Lists.newArrayList(toBuild, toRetry);
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project dsl-devkit by dsldevkit.
the class RebuildingXtextBuilder method doBuild.
/**
* Like the super implementation, except the build is not triggered if
* both toBeDeleted and toBeUpdated are empty. {@inheritDoc}
*/
@SuppressWarnings("nls")
@Override
protected void doBuild(final ToBeBuilt toBeBuilt, final IProgressMonitor monitor, final BuildType type) throws CoreException {
if (toBeBuilt.getToBeDeleted().size() != 0 || toBeBuilt.getToBeUpdated().size() != 0) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Starting " + type.name() + " build:" + "\ndeleted(" + toBeBuilt.getToBeDeleted().size() + ")=" + toBeBuilt.getToBeDeleted().toString() + "\nupdated(" + toBeBuilt.getToBeUpdated().size() + ")=" + toBeBuilt.getToBeUpdated().toString());
}
// build + participant + rebuild
SubMonitor progress = SubMonitor.convert(monitor, 1 + 1 + 1);
ResourceSet resourceSet = getResourceSetProvider().get(getProject());
resourceSet.getLoadOptions().put(ResourceDescriptionsProvider.NAMED_BUILDER_SCOPE, Boolean.TRUE);
if (resourceSet instanceof ResourceSetImpl) {
((ResourceSetImpl) resourceSet).setURIResourceMap(Maps.<URI, Resource>newHashMap());
}
BuildData buildData = new BuildData(getProject().getName(), resourceSet, toBeBuilt, queuedBuildData);
ImmutableList<Delta> deltas = builderState.update(buildData, progress.newChild(1));
if (participant != null) {
final BuildContext buildContext = new BuildContext(this, resourceSet, deltas, type);
// remember the current workspace tree
final ElementTree oldTree = ((Workspace) ResourcesPlugin.getWorkspace()).getElementTree();
oldTree.immutable();
participant.build(buildContext, progress.newChild(1));
if (buildContext.isRebuildRequired() && rebuilds++ <= 2) {
final ElementTree newTree = ((Workspace) ResourcesPlugin.getWorkspace()).getElementTree();
newTree.immutable();
final ResourceDelta generatedDelta = ResourceDeltaFactory.computeDelta((Workspace) ResourcesPlugin.getWorkspace(), oldTree, newTree, getProject().getFullPath(), -1);
// rebuild the generated delta
ResourcesPlugin.getWorkspace().checkpoint(false);
incrementalBuild(generatedDelta, progress.newChild(1));
}
} else {
progress.worked(2);
}
resourceSet.getResources().clear();
resourceSet.eAdapters().clear();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Build done.");
}
} else if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Ignoring empty " + type.name() + " build.");
}
}
use of org.eclipse.xtext.resource.IResourceDescription.Delta in project dsl-devkit by dsldevkit.
the class FixedDirtyStateEditorSupport method isReparseRequired.
/**
* {@inheritDoc}
*/
@Override
protected boolean isReparseRequired(final XtextResource resource, final Event event) {
// NOPMD (NPath complexity)
IResourceDescription.Manager resourceDescriptionManager = resource.getResourceServiceProvider().getResourceDescriptionManager();
final IResourceDescription description = resourceDescriptionManager.getResourceDescription(resource);
// The DefaultResourceDescriptionManager honors container visibility only for platform and archive URIs... oh well; let's do it explicitly here.
final IContainer.Manager containerManager = resource.getResourceServiceProvider().getContainerManager();
// Unfortunately, we need a Collection in the call to isAffected() below...
List<Delta> visibleChanges = Lists.newArrayList(Iterables.filter(event.getDeltas(), new Predicate<Delta>() {
private List<IContainer> containers;
private Iterable<IContainer> getContainers() {
// Getting the containers is a relatively expensive operation. We delay doing this until we really need it.
if (containers == null) {
containers = containerManager.getVisibleContainers(description, resourceDescriptions);
}
return containers;
}
@Override
public boolean apply(final Delta delta) {
if (delta.haveEObjectDescriptionsChanged()) {
if (delta.getNew() == null) {
// If it was deleted, we don't know whether it was visible. Hmphhh.
return true;
}
if (delta.getUri().isFile()) {
// Apparently these are java-resources, which are always visible?! (c.f. Xtext bug 383919.)
return true;
}
for (IContainer container : getContainers()) {
if (container.hasResourceDescription(delta.getUri())) {
return true;
}
}
}
return false;
}
}));
// Fix Xtext bug 383919: delegate the whole checking to the description manager, which may have optimized processing in place anyway.
if (resourceDescriptionManager.isAffected(visibleChanges, description, resourceDescriptions)) {
return true;
}
if (!isDirty() && !getDirtyStateManager().hasContent(resource.getURI())) {
IResourceDescription originalDescription = resourceDescriptions.getResourceDescription(resource.getURI());
if (originalDescription != null && descriptionUtils != null) {
Set<URI> outgoingReferences = descriptionUtils.collectOutgoingReferences(originalDescription);
for (Delta delta : visibleChanges) {
if (outgoingReferences.contains(delta.getUri())) {
return true;
}
}
}
}
return false;
}
Aggregations