use of org.eclipse.jface.text.ISynchronizable in project xtext-eclipse by eclipse.
the class EmbeddedEditorModelAccess method setModel.
protected void setModel(XtextDocument document, String prefix, String editablePart, String suffix) {
if (this.insertLineBreaks) {
String delimiter = document.getDefaultLineDelimiter();
prefix = prefix + delimiter;
suffix = delimiter + suffix;
}
String model = prefix + editablePart + suffix;
document.set(model);
XtextResource resource = createResource(model);
document.setInput(resource);
AnnotationModel annotationModel = new AnnotationModel();
if (document instanceof ISynchronizable) {
Object lock = ((ISynchronizable) document).getLockObject();
if (lock == null) {
lock = new Object();
((ISynchronizable) document).setLockObject(lock);
}
((ISynchronizable) annotationModel).setLockObject(lock);
}
this.viewer.setDocument(document, annotationModel, prefix.length(), editablePart.length());
}
use of org.eclipse.jface.text.ISynchronizable in project eclipse.platform.text by eclipse.
the class DocumentLineDiffer method initialize.
/**
* (Re-)initializes the differ using the current reference and <code>DiffInitializer</code>.
*
* @since 3.2 protected for testing reasons, package visible before
*/
protected synchronized void initialize() {
// make new incoming changes go into the queue of stored events, plus signal we can't restore.
fState = INITIALIZING;
if (fRightDocument == null)
return;
// there is no point in receiving updates before the job we get a new copy of the document for diffing
fIgnoreDocumentEvents = true;
if (fLeftDocument != null) {
fLeftDocument.removeDocumentListener(this);
fLeftDocument = null;
fLeftEquivalent = null;
}
// if there already is a job:
// return if it has not started yet, cancel it if already running
final Job oldJob = fInitializationJob;
if (oldJob != null) {
// don't chain up jobs if there is one waiting already.
if (oldJob.getState() == Job.WAITING) {
oldJob.wakeUp(INITIALIZE_DELAY);
return;
}
oldJob.cancel();
}
fInitializationJob = new Job(QuickDiffMessages.quickdiff_initialize) {
/*
* This is run in a different thread. As the documents might be synchronized, never ever
* access the documents in a synchronized section or expect deadlocks. See
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=44692
*/
@Override
public IStatus run(IProgressMonitor monitor) {
// It will return relatively quickly as RangeDifferencer supports canceling
if (oldJob != null)
try {
oldJob.join();
} catch (InterruptedException e) {
// will not happen as no one interrupts our thread
Assert.isTrue(false);
}
// 2: get the reference document
IQuickDiffReferenceProvider provider = fReferenceProvider;
final IDocument left;
try {
left = provider == null ? null : provider.getReference(monitor);
} catch (CoreException e) {
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
clearModel();
fireModelChanged();
return e.getStatus();
}
} catch (OperationCanceledException e) {
return Status.CANCEL_STATUS;
}
// Getting our own copies of the documents for offline diffing.
//
// We need to make sure that we do get all document modifications after
// copying the documents as we want to re-inject them later on to become consistent.
// fRightDocument, but not subject to change
IDocument right = fRightDocument;
// the copy of the actual (right) document
IDocument actual = null;
// the copy of the reference (left) document
IDocument reference = null;
synchronized (DocumentLineDiffer.this) {
// 4: take an early exit if the documents are not valid
if (left == null || right == null) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
clearModel();
fireModelChanged();
return Status.OK_STATUS;
}
// set the reference document
fLeftDocument = left;
// start listening to document events.
fIgnoreDocumentEvents = false;
}
// accessing the reference document from a different thread - reference providers need
// to be able to deal with this.
left.addDocumentListener(DocumentLineDiffer.this);
// create the reference copy - note that any changes on the
// reference will trigger re-initialization anyway
reference = createCopy(left);
if (reference == null)
return Status.CANCEL_STATUS;
// create the actual copy
Object lock = null;
if (right instanceof ISynchronizable)
lock = ((ISynchronizable) right).getLockObject();
if (lock != null) {
// the document
synchronized (lock) {
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
fStoredEvents.clear();
actual = createUnprotectedCopy(right);
}
}
} else {
// b) cannot lock the document
// Now this is fun. The reference documents may be PartiallySynchronizedDocuments
// which will result in a deadlock if they get changed externally before we get
// our exclusive copies.
// Here's what we do: we try over and over (without synchronization) to get copies
// without interleaving modification. If there is a document change, we just repeat.
int i = 0;
do {
// this is an arbitrary emergency exit in case a referenced document goes nuts
if (i++ == 100)
return new Status(IStatus.ERROR, TextEditorPlugin.PLUGIN_ID, IStatus.OK, NLSUtility.format(QuickDiffMessages.quickdiff_error_getting_document_content, new Object[] { left.getClass(), right.getClass() }), null);
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
fStoredEvents.clear();
}
// access documents non synchronized:
// get an exclusive copy of the actual document
actual = createCopy(right);
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
if (fStoredEvents.size() == 0 && actual != null)
break;
}
} while (true);
}
IHashFunction hash = new DJBHashFunction();
DocumentEquivalenceClass leftEquivalent = new DocumentEquivalenceClass(reference, hash);
fLeftEquivalent = leftEquivalent;
IRangeComparator ref = new DocEquivalenceComparator(leftEquivalent, null);
DocumentEquivalenceClass rightEquivalent = new DocumentEquivalenceClass(actual, hash);
fRightEquivalent = rightEquivalent;
IRangeComparator act = new DocEquivalenceComparator(rightEquivalent, null);
ArrayList<QuickDiffRangeDifference> diffs = asQuickDiffRangeDifference(RangeDifferencer.findRanges(fRangeDiffFactory, monitor, ref, act));
// re-inject stored events to get up to date.
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
// set the new differences so we can operate on them
fDifferences = diffs;
}
// re-inject events accumulated in the meantime.
try {
do {
DocumentEvent event;
synchronized (DocumentLineDiffer.this) {
if (isCanceled(monitor))
return Status.CANCEL_STATUS;
if (fStoredEvents.isEmpty()) {
// we are back in sync with the life documents
fInitializationJob = null;
fState = SYNCHRONIZED;
fLastDifference = null;
// replace the private documents with the actual
leftEquivalent.setDocument(left);
rightEquivalent.setDocument(right);
break;
}
event = fStoredEvents.remove(0);
}
// access documents non synchronized:
IDocument copy = null;
if (event.fDocument == right)
copy = actual;
else if (event.fDocument == left)
copy = reference;
else
Assert.isTrue(false);
// copy the event to inject it into our diff copies
// don't modify the original event! See https://bugs.eclipse.org/bugs/show_bug.cgi?id=134227
event = new DocumentEvent(copy, event.fOffset, event.fLength, event.fText);
handleAboutToBeChanged(event);
// inject the event into our private copy
actual.replace(event.fOffset, event.fLength, event.fText);
handleChanged(event);
} while (true);
} catch (BadLocationException e) {
left.removeDocumentListener(DocumentLineDiffer.this);
clearModel();
initialize();
return Status.CANCEL_STATUS;
}
fireModelChanged();
return Status.OK_STATUS;
}
private boolean isCanceled(IProgressMonitor monitor) {
return fInitializationJob != this || monitor != null && monitor.isCanceled();
}
private void clearModel() {
synchronized (DocumentLineDiffer.this) {
fLeftDocument = null;
fLeftEquivalent = null;
fInitializationJob = null;
fStoredEvents.clear();
fLastDifference = null;
fDifferences.clear();
}
}
/**
* Creates a copy of <code>document</code> and catches any
* exceptions that may occur if the document is modified concurrently.
* Only call this method in a synchronized block if the document is
* an ISynchronizable and has been locked, as document.get() is called
* and may result in a deadlock otherwise.
*
* @param document the document to create a copy of
* @return a copy of the document, or <code>null</code> if an exception was thrown
*/
private IDocument createCopy(IDocument document) {
Assert.isNotNull(document);
// this fixes https://bugs.eclipse.org/bugs/show_bug.cgi?id=56091
try {
return createUnprotectedCopy(document);
} catch (NullPointerException e) {
} catch (ArrayStoreException e) {
} catch (IndexOutOfBoundsException e) {
} catch (ConcurrentModificationException e) {
} catch (NegativeArraySizeException e) {
}
return null;
}
private IDocument createUnprotectedCopy(IDocument document) {
return new Document(document.get());
}
};
fInitializationJob.setSystem(true);
fInitializationJob.setPriority(Job.DECORATE);
fInitializationJob.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
fInitializationJob.schedule(INITIALIZE_DELAY);
}
use of org.eclipse.jface.text.ISynchronizable in project titan.EclipsePlug-ins by eclipse.
the class TTCNPPEditor method updateInactiveCodeAnnotations.
public void updateInactiveCodeAnnotations(final List<Location> inactiveCodeLocations) {
if ((inactiveCodeLocations == null || inactiveCodeLocations.isEmpty()) && (inactiveCodeAnnotations == null || inactiveCodeAnnotations.length == 0)) {
return;
}
IEditorInput editorInput = getEditorInput();
if (editorInput == null) {
return;
}
IDocumentProvider documentProvider = getDocumentProvider();
if (documentProvider == null) {
return;
}
IAnnotationModel annotationModel = documentProvider.getAnnotationModel(editorInput);
if (annotationModel == null) {
return;
}
Object lockObject = (annotationModel instanceof ISynchronizable) ? ((ISynchronizable) annotationModel).getLockObject() : annotationModel;
synchronized (lockObject) {
Map<Annotation, Position> annotationMap = new HashMap<Annotation, Position>();
if (inactiveCodeLocations != null) {
for (Location loc : inactiveCodeLocations) {
Annotation annotationToAdd = new Annotation(INACTIVE_CODE_ANNOTATION_TYPE, false, "Inactive code");
Position position = new Position(loc.getOffset(), loc.getEndOffset() - loc.getOffset());
annotationMap.put(annotationToAdd, position);
}
}
if (annotationModel instanceof IAnnotationModelExtension) {
((IAnnotationModelExtension) annotationModel).replaceAnnotations(inactiveCodeAnnotations, annotationMap);
} else {
if (inactiveCodeAnnotations != null) {
for (Annotation annotationToRemove : inactiveCodeAnnotations) {
annotationModel.removeAnnotation(annotationToRemove);
}
}
for (Map.Entry<Annotation, Position> entry : annotationMap.entrySet()) {
annotationModel.addAnnotation(entry.getKey(), entry.getValue());
}
}
inactiveCodeAnnotations = annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
}
}
use of org.eclipse.jface.text.ISynchronizable in project eclipse.platform.text by eclipse.
the class SourceViewer method setDocument.
@Override
public void setDocument(IDocument document, IAnnotationModel annotationModel, int modelRangeOffset, int modelRangeLength) {
disposeVisualAnnotationModel();
if (annotationModel != null && document != null) {
fVisualAnnotationModel = createVisualAnnotationModel(annotationModel);
// Make sure the visual model uses the same lock as the underlying model
if (annotationModel instanceof ISynchronizable && fVisualAnnotationModel instanceof ISynchronizable) {
ISynchronizable sync = (ISynchronizable) fVisualAnnotationModel;
sync.setLockObject(((ISynchronizable) annotationModel).getLockObject());
}
fVisualAnnotationModel.connect(document);
}
if (modelRangeOffset == -1 && modelRangeLength == -1)
super.setDocument(document);
else
super.setDocument(document, modelRangeOffset, modelRangeLength);
if (fVerticalRuler != null)
fVerticalRuler.setModel(fVisualAnnotationModel);
if (fOverviewRuler != null)
fOverviewRuler.setModel(fVisualAnnotationModel);
}
use of org.eclipse.jface.text.ISynchronizable in project eclipse.platform.text by eclipse.
the class TextFileDocumentProvider method setUpSynchronization.
/**
* Sets up the synchronization for the document
* and the annotation mode.
*
* @param info the file info
* @since 3.2
*/
protected void setUpSynchronization(FileInfo info) {
if (info == null || info.fTextFileBuffer == null)
return;
IDocument document = info.fTextFileBuffer.getDocument();
IAnnotationModel model = info.fModel;
if (document instanceof ISynchronizable) {
Object lock = ((ISynchronizable) document).getLockObject();
if (lock == null) {
lock = new Object();
((ISynchronizable) document).setLockObject(lock);
}
if (model instanceof ISynchronizable)
((ISynchronizable) model).setLockObject(lock);
}
}
Aggregations