diff options
author | nitind | 2011-03-02 15:27:00 +0000 |
---|---|---|
committer | nitind | 2011-03-02 15:27:00 +0000 |
commit | 0bc10cc56f010247a7a473af8e1b2d2782457a74 (patch) | |
tree | 8b5ebc8cbf894e1257acbd7549f1db3f7835bd50 /bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text | |
parent | 9039eeb528e8460702d9820f089c077f10c70ea5 (diff) | |
download | webtools.sourceediting-201103021533.tar.gz webtools.sourceediting-201103021533.tar.xz webtools.sourceediting-201103021533.zip |
This commit was manufactured by cvs2svn to create tag 'v201103021533'.v201103021533
Diffstat (limited to 'bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text')
23 files changed, 0 insertions, 8531 deletions
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java deleted file mode 100644 index 9b404c6368..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java +++ /dev/null @@ -1,2979 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2010 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * Jesper Steen Møller - initial IDocumentExtension4 support - #102822 - * (see also #239115) - * David Carver (Intalio) - bug 300434 - Make inner classes static where possible - * David Carver (Intalio) - bug 300443 - some constants aren't static final - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import java.io.Reader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.eclipse.core.runtime.ISafeRunnable; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.SafeRunner; -import org.eclipse.core.runtime.preferences.IScopeContext; -import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.BadPartitioningException; -import org.eclipse.jface.text.BadPositionCategoryException; -import org.eclipse.jface.text.DefaultLineTracker; -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.DocumentPartitioningChangedEvent; -import org.eclipse.jface.text.DocumentRewriteSession; -import org.eclipse.jface.text.DocumentRewriteSessionEvent; -import org.eclipse.jface.text.DocumentRewriteSessionType; -import org.eclipse.jface.text.FindReplaceDocumentAdapter; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IDocumentExtension; -import org.eclipse.jface.text.IDocumentExtension3; -import org.eclipse.jface.text.IDocumentExtension4; -import org.eclipse.jface.text.IDocumentListener; -import org.eclipse.jface.text.IDocumentPartitioner; -import org.eclipse.jface.text.IDocumentPartitionerExtension; -import org.eclipse.jface.text.IDocumentPartitionerExtension2; -import org.eclipse.jface.text.IDocumentPartitionerExtension3; -import org.eclipse.jface.text.IDocumentPartitioningListener; -import org.eclipse.jface.text.IDocumentPartitioningListenerExtension; -import org.eclipse.jface.text.IDocumentPartitioningListenerExtension2; -import org.eclipse.jface.text.IDocumentRewriteSessionListener; -import org.eclipse.jface.text.ILineTracker; -import org.eclipse.jface.text.ILineTrackerExtension; -import org.eclipse.jface.text.IPositionUpdater; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.ITextStore; -import org.eclipse.jface.text.ITypedRegion; -import org.eclipse.jface.text.Position; -import org.eclipse.jface.text.TypedRegion; -import org.eclipse.wst.sse.core.internal.Logger; -import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory; -import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento; -import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser; -import org.eclipse.wst.sse.core.internal.provisional.events.AboutToBeChangedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener; -import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener; -import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser; -import org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner; -import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager; -import org.eclipse.wst.sse.core.internal.undo.StructuredTextUndoManager; -import org.eclipse.wst.sse.core.internal.util.Assert; -import org.eclipse.wst.sse.core.internal.util.Debug; -import org.eclipse.wst.sse.core.internal.util.Utilities; - - -/** - * The standard implementation of structured document. - */ -public class BasicStructuredDocument implements IStructuredDocument, IDocumentExtension, IDocumentExtension3, IDocumentExtension4, CharSequence, IRegionComparible { - - /** - * This ThreadLocal construct is used so each thread can maintain its only - * pointer to the double linked list that manages the documents regions. - * The only thing we "gaurd" for is that a previously cached region has - * been deleted. - * - * The object that is kept in the thread local's map, is just a pointer to - * an array position. That's because the object there needs to be "free" - * from references to other objects, or it will not be garbage collected. - */ - private class CurrentDocumentRegionCache { - // I'm assuming for now there would never be so many threads that - // this arrayList needs to be bounded, or 'cleaned up'. - // this assumption should be tested in practice and long running - // jobs -- found not to be a good assumption. See below. - private List cachedRegionPositionArray = Collections.synchronizedList(new ArrayList()); - private final boolean DEBUG = false; - private static final int MAX_SIZE = 50; - - - private ThreadLocal threadLocalCachePosition = new ThreadLocal(); - - IStructuredDocumentRegion get() { - IStructuredDocumentRegion region = null; - int pos = getThreadLocalPosition(); - try { - region = (IStructuredDocumentRegion) cachedRegionPositionArray.get(pos); - } - catch (IndexOutOfBoundsException e) { - // even though the cachedRegionPosition is synchronized, - // that just means each access is syncronized, its - // still possible for another thread to cause it to - // be cleared, after this thread gets it position. - // So, if that happens, all we can do is reset to beginning. - // This should be extremely rare (in other words, probably - // not worth using synchronized blocks - // to access cachedRegionPositionArray. - reinitThreadLocalPosition(); - resetToInitialState(); - } - if (region == null) { - region = resetToInitialState(); - } - else - // region not null - if (region.isDeleted()) { - region = resetToInitialState(); - } - return region; - } - - private int getThreadLocalPosition() { - Object threadLocalObject = threadLocalCachePosition.get(); - int pos = -1; - if (threadLocalObject == null) { - - pos = reinitThreadLocalPosition(); - } - else { - pos = ((Integer) threadLocalObject).intValue(); - } - return pos; - } - - /** - * @return - */ - private int reinitThreadLocalPosition() { - Integer position; - int pos; - // TODO_future: think of a better solution that doesn't - // require this kludge. This is especially required because - // some infrasture, such as reconciler, actually null out - // their thread object and recreate it, 500 msecs later - // (approximately). - // Note: the likely solution in future is to clear after every - // heavy use of getCachedRegion, such as in creating node - // lists, or reparsing or partioning. - if (cachedRegionPositionArray.size() > MAX_SIZE) { - cachedRegionPositionArray.clear(); - if (DEBUG) { - System.out.println("cachedRegionPositionArray cleared at size " + MAX_SIZE); //$NON-NLS-1$ - } - } - position = new Integer(cachedRegionPositionArray.size()); - threadLocalCachePosition.set(position); - cachedRegionPositionArray.add(position.intValue(), null); - pos = position.intValue(); - return pos; - } - - private IStructuredDocumentRegion resetToInitialState() { - IStructuredDocumentRegion region; - region = getFirstStructuredDocumentRegion(); - set(region); - return region; - } - - void set(IStructuredDocumentRegion region) { - try { - int pos = getThreadLocalPosition(); - cachedRegionPositionArray.set(pos, region); - } - catch (IndexOutOfBoundsException e) { - // even though the cachedRegionPosition is synchronized, - // that just means each access is syncronized, its - // still possible for another thread to cause it to - // be cleared, after this thread gets it position. - // So, if that happens, all we can do is reset to beginning. - // This should be extremely rare (in other words, probably - // not worth using synchronized blocks - // to access cachedRegionPositionArray. - reinitThreadLocalPosition(); - resetToInitialState(); - } - } - } - - /** - * This NullDocumentEvent is used to complete the "aboutToChange" and - * "changed" cycle, when in fact the original change is no longer valid. - * The only known (valid) case of this is when a model re-initialize takes - * place, which causes setText to be called in the middle of some previous - * change. [This architecture will be improved in future]. - */ - public class NullDocumentEvent extends DocumentEvent { - public NullDocumentEvent() { - this(BasicStructuredDocument.this, 0, 0, ""); //$NON-NLS-1$ - } - - private NullDocumentEvent(IDocument doc, int offset, int length, String text) { - super(doc, offset, length, text); - } - } - - static class RegisteredReplace { - /** The owner of this replace operation. */ - IDocumentListener fOwner; - /** The replace operation */ - IDocumentExtension.IReplace fReplace; - - /** - * Creates a new bundle object. - * - * @param owner - * the document listener owning the replace operation - * @param replace - * the replace operation - */ - RegisteredReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) { - fOwner = owner; - fReplace = replace; - } - } - - /** - * these control variable isn't mark as 'final' since there's some unit - * tests that manipulate it. For final product, it should be. - */ - - private static boolean USE_LOCAL_THREAD = true; - - /** - * purely for debugging/performance measurements In practice, would always - * be 'true'. (and should never be called by called by clients). Its not - * 'final' or private just so it can be varied during - * debugging/performance measurement runs. - * - * @param use_local_thread - */ - public static void setUSE_LOCAL_THREAD(final boolean use_local_thread) { - USE_LOCAL_THREAD = use_local_thread; - } - - private IStructuredDocumentRegion cachedDocumentRegion; - private EncodingMemento encodingMemento; - private boolean fAcceptPostNotificationReplaces = true; - private CurrentDocumentRegionCache fCurrentDocumentRegionCache; - private DocumentEvent fDocumentEvent; - private IDocumentListener[] fDocumentListeners; - - /** - * The registered document partitioners. - */ - private Map fDocumentPartitioners; - /** The registered document partitioning listeners */ - private List fDocumentPartitioningListeners; - private IStructuredDocumentRegion firstDocumentRegion; - private RegionParser fParser; - private GenericPositionManager fPositionManager; - private List fPostNotificationChanges; - private IDocumentListener[] fPrenotifiedDocumentListeners; - private int fReentranceCount = 0; - private IStructuredTextReParser fReParser; - private int fStoppedCount = 0; - - private ITextStore fStore; - private Object[] fStructuredDocumentAboutToChangeListeners; - private Object[] fStructuredDocumentChangedListeners; - private Object[] fStructuredDocumentChangingListeners; - - private List fDocumentRewriteSessionListeners; - - private ILineTracker fTracker; - private IStructuredTextUndoManager fUndoManager; - private IStructuredDocumentRegion lastDocumentRegion; - - private byte[] listenerLock = new byte[0]; - private NullDocumentEvent NULL_DOCUMENT_EVENT; - - /** - * Theoretically, a document can contain mixed line delimiters, but the - * user's preference is usually to be internally consistent. - */ - private String fInitialLineDelimiter; - private static final String READ_ONLY_REGIONS_CATEGORY = "_READ_ONLY_REGIONS_CATEGORY_"; //$NON-NLS-1$ - /** - * Current rewrite session, or none if not presently rewriting. - */ - private DocumentRewriteSession fActiveRewriteSession; - /** - * Last modification stamp, automatically updated on change. - */ - private long fModificationStamp; - /** - * Keeps track of next modification stamp. - */ - private long fNextModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; - /** - * debug variable only - * - * @param parser - */ - private long startStreamTime; - /** - * debug variable only - * - * @param parser - */ - private long startTime; - - public BasicStructuredDocument() { - super(); - fCurrentDocumentRegionCache = new CurrentDocumentRegionCache(); - setTextStore(new StructuredDocumentTextStore(50, 300)); - setLineTracker(new DefaultLineTracker()); - NULL_DOCUMENT_EVENT = new NullDocumentEvent(); - - internal_addPositionCategory(READ_ONLY_REGIONS_CATEGORY); - internal_addPositionUpdater(new DeleteEqualPositionUpdater(READ_ONLY_REGIONS_CATEGORY)); - - } - - /** - * This is the primary way to get a new structuredDocument. Its best to - * use the factory methods in ModelManger to create a new - * IStructuredDocument, since it will get and initialize the parser - * according to the desired content type. - */ - public BasicStructuredDocument(RegionParser parser) { - this(); - Assert.isNotNull(parser, "Program Error: IStructuredDocument can not be created with null parser"); //$NON-NLS-1$ - // go through setter in case there is side effects - internal_setParser(parser); - } - - private void _clearDocumentEvent() { - // no hard and fast requirement to null out ... just seems like - // a good idea, since we are done with it. - fDocumentEvent = null; - } - - private void _fireDocumentAboutToChange(Object[] listeners) { - // most DocumentAboutToBeChanged listeners do not anticipate - // DocumentEvent == null. So make sure documentEvent is not - // null. (this should never happen, yet it does sometimes) - if (fDocumentEvent == null) { - fDocumentEvent = new NullDocumentEvent(); - } - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (listeners != null) { - Object[] holdListeners = listeners; - // Note: the docEvent is created in replaceText API - // fire - for (int i = 0; i < holdListeners.length; i++) { - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - startTime = System.currentTimeMillis(); - } - // safeguard from listeners that throw exceptions - try { - // this is a safe cast, since addListners requires a - // IStructuredDocumentListener - ((IDocumentListener) holdListeners[i]).documentAboutToBeChanged(fDocumentEvent); - } - catch (Exception exception) { - Logger.logException(exception); - } - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - long stopTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - } - - private void notifyDocumentPartitionersAboutToChange(DocumentEvent documentEvent) { - if (fDocumentPartitioners != null) { - Iterator e = fDocumentPartitioners.values().iterator(); - while (e.hasNext()) { - IDocumentPartitioner p = (IDocumentPartitioner) e.next(); - // safeguard from listeners that throw exceptions - try { - p.documentAboutToBeChanged(documentEvent); - } - catch (Exception exception) { - Logger.logException(exception); - } - } - } - } - - private void _fireDocumentChanged(Object[] listeners, StructuredDocumentEvent event) { - - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (listeners != null) { - Object[] holdListeners = listeners; - // NOTE: document event is created in replace Text API and setText - // API - // now fire - for (int i = 0; i < holdListeners.length; i++) { - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - startTime = System.currentTimeMillis(); - } - - // safeguard from listeners that throw exceptions - try { - // this is a safe cast, since addListners requires a - // IStructuredDocumentListener - // Notes: fDocumentEvent can be "suddenly" null, if one of - // the - // previous changes - // caused a "setText" to be called. The only known case of - // this - // is a model reset - // due to page directive changing. Eventually we should - // change - // archetecture to have - // event que and be able to "cancel" pending events, but - // for - // now, we'll just pass a - // NullDocumentEvent. By the way, it is important to send - // something, since clients might - // have indeterminant state due to "aboutToChange" being - // sent - // earlier. - if (fDocumentEvent == null) { - ((IDocumentListener) holdListeners[i]).documentChanged(NULL_DOCUMENT_EVENT); - } - else { - ((IDocumentListener) holdListeners[i]).documentChanged(fDocumentEvent); - } - } - catch (Exception exception) { - Logger.logException(exception); - } - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - long stopTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - } - - private void notifyDocumentPartitionersDocumentChanged(DocumentEvent documentEvent) { - if (fDocumentPartitioners != null) { - Iterator e = fDocumentPartitioners.values().iterator(); - while (e.hasNext()) { - IDocumentPartitioner p = (IDocumentPartitioner) e.next(); - // safeguard from listeners that throw exceptions - try { - if (p instanceof IDocumentPartitionerExtension) { - // IRegion changedPartion = - ((IDocumentPartitionerExtension) p).documentChanged2(documentEvent); - } - else { - p.documentChanged(documentEvent); - } - } - catch (Exception exception) { - Logger.logException(exception); - } - } - } - } - - - private void _fireEvent(Object[] listeners, NoChangeEvent event) { - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (listeners != null) { - Object[] holdListeners = listeners; - for (int i = 0; i < holdListeners.length; i++) { - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - startTime = System.currentTimeMillis(); - } - // safeguard from listeners that throw exceptions - try { - // this is a safe cast, since addListners requires a - // IStructuredDocumentListener - ((IStructuredDocumentListener) holdListeners[i]).noChange(event); - } - catch (Exception exception) { - Logger.logException(exception); - } - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - long stopTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - } - - private void _fireEvent(Object[] listeners, RegionChangedEvent event) { - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (listeners != null) { - Object[] holdListeners = listeners; - for (int i = 0; i < holdListeners.length; i++) { - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - startTime = System.currentTimeMillis(); - } - // safeguard from listeners that throw exceptions - try { - // this is a safe cast, since addListners requires a - // IStructuredDocumentListener - ((IStructuredDocumentListener) holdListeners[i]).regionChanged(event); - } - catch (Exception exception) { - Logger.logException(exception); - } - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - long stopTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - } - - private void _fireEvent(Object[] listeners, RegionsReplacedEvent event) { - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (listeners != null) { - Object[] holdListeners = listeners; - for (int i = 0; i < holdListeners.length; i++) { - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - startTime = System.currentTimeMillis(); - } - // safeguard from listeners that throw exceptions - try { - // this is a safe cast, since addListners requires a - // IStructuredDocumentListener - ((IStructuredDocumentListener) holdListeners[i]).regionsReplaced(event); - } - catch (Exception exception) { - Logger.logException(exception); - } - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - long stopTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - } - - private void _fireEvent(Object[] listeners, StructuredDocumentRegionsReplacedEvent event) { - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (listeners != null) { - Object[] holdListeners = listeners; - for (int i = 0; i < holdListeners.length; i++) { - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - startTime = System.currentTimeMillis(); - } - // safeguard from listeners that throw exceptions - try { - // this is a safe cast, since addListners requires a - // IStructuredDocumentListener - ((IStructuredDocumentListener) holdListeners[i]).nodesReplaced(event); - } - catch (Exception exception) { - Logger.logException(exception); - } - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - long stopTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - } - - private void _fireStructuredDocumentAboutToChange(Object[] listeners) { - // we must assign listeners to local variable, since the add and - // remove - // listner - // methods can change the actual instance of the listener array from - // another thread - if (listeners != null) { - Object[] holdListeners = listeners; - // Note: the docEvent is created in replaceText API - // fire - for (int i = 0; i < holdListeners.length; i++) { - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - startTime = System.currentTimeMillis(); - } - // safeguard from listeners that throw exceptions - try { - // notice the AboutToBeChangedEvent is created from the - // DocumentEvent, since it is (nearly) - // the same information. ?What to do about - // originalRequester? - if (fDocumentEvent == null) { - fDocumentEvent = new NullDocumentEvent(); - } - AboutToBeChangedEvent aboutToBeChangedEvent = new AboutToBeChangedEvent(this, null, fDocumentEvent.getText(), fDocumentEvent.getOffset(), fDocumentEvent.getLength()); - // this is a safe cast, since addListners requires a - // IStructuredDocumentListener - ((IModelAboutToBeChangedListener) holdListeners[i]).modelAboutToBeChanged(aboutToBeChangedEvent); - } - catch (Exception exception) { - Logger.logException(exception); - } - if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) { - long stopTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$ - } - } - } - } - - protected void acquireLock() { - // do nothing here in super class - } - - /** - * addModelAboutToBeChangedListener method comment. - */ - public void addDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) { - synchronized (listenerLock) { - - // make sure listener is not already in listening - // (and if it is, print a warning to aid debugging, if needed) - if (!Utilities.contains(fStructuredDocumentAboutToChangeListeners, listener)) { - int oldSize = 0; - if (fStructuredDocumentAboutToChangeListeners != null) { - // normally won't be null, but we need to be sure, for - // first - // time through - oldSize = fStructuredDocumentAboutToChangeListeners.length; - } - int newSize = oldSize + 1; - Object[] newListeners = new Object[newSize]; - if (fStructuredDocumentAboutToChangeListeners != null) { - System.arraycopy(fStructuredDocumentAboutToChangeListeners, 0, newListeners, 0, oldSize); - } - // add listener to last position - newListeners[newSize - 1] = listener; - // - // now switch new for old - fStructuredDocumentAboutToChangeListeners = newListeners; - // - } - } - } - - /** - * The StructuredDocumentListners and ModelChagnedListeners are very - * similar. They both receive identical events. The difference is the - * timing. The "pure" StructuredDocumentListners are notified after the - * structuredDocument has been changed, but before other, related models - * may have been changed such as the Structural Model. The Structural - * model is in fact itself a "pure" StructuredDocumentListner. The - * ModelChangedListeners can rest assured that all models and data have - * been updated from the change by the tiem they are notified. This is - * especially important for the text widget, for example, which may rely - * on both structuredDocument and structural model information. - */ - public void addDocumentChangedListener(IStructuredDocumentListener listener) { - synchronized (listenerLock) { - - if (Debug.debugStructuredDocument) { - System.out.println("IStructuredDocument::addModelChangedListener. Request to add an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$ - } - // make sure listener is not already in listening - // (and if it is, print a warning to aid debugging, if needed) - if (Utilities.contains(fStructuredDocumentChangedListeners, listener)) { - if (Debug.displayWarnings) { - System.out.println("IStructuredDocument::addModelChangedListener. listener " + listener + " was addeded more than once. "); //$NON-NLS-2$//$NON-NLS-1$ - } - } - else { - if (Debug.debugStructuredDocument) { - System.out.println("IStructuredDocument::addModelChangedListener. Adding an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$ - } - int oldSize = 0; - if (fStructuredDocumentChangedListeners != null) { - // normally won't be null, but we need to be sure, for - // first - // time through - oldSize = fStructuredDocumentChangedListeners.length; - } - int newSize = oldSize + 1; - Object[] newListeners = new Object[newSize]; - if (fStructuredDocumentChangedListeners != null) { - System.arraycopy(fStructuredDocumentChangedListeners, 0, newListeners, 0, oldSize); - } - // add listener to last position - newListeners[newSize - 1] = listener; - // - // now switch new for old - fStructuredDocumentChangedListeners = newListeners; - // - // when a listener is added, - // send the new model event to that one particular listener, - // so it - // can initialize itself with the current state of the model - // listener.newModel(new NewModelEvent(this, listener)); - } - } - } - - public void addDocumentChangingListener(IStructuredDocumentListener listener) { - synchronized (listenerLock) { - - if (Debug.debugStructuredDocument) { - System.out.println("IStructuredDocument::addStructuredDocumentListener. Request to add an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$ - } - // make sure listener is not already in listening - // (and if it is, print a warning to aid debugging, if needed) - if (Utilities.contains(fStructuredDocumentChangingListeners, listener)) { - if (Debug.displayWarnings) { - System.out.println("IStructuredDocument::addStructuredDocumentListener. listener " + listener + " was addeded more than once. "); //$NON-NLS-2$//$NON-NLS-1$ - } - } - else { - if (Debug.debugStructuredDocument) { - System.out.println("IStructuredDocument::addStructuredDocumentListener. Adding an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$ - } - int oldSize = 0; - if (fStructuredDocumentChangingListeners != null) { - // normally won't be null, but we need to be sure, for - // first - // time through - oldSize = fStructuredDocumentChangingListeners.length; - } - int newSize = oldSize + 1; - Object[] newListeners = new Object[newSize]; - if (fStructuredDocumentChangingListeners != null) { - System.arraycopy(fStructuredDocumentChangingListeners, 0, newListeners, 0, oldSize); - } - // add listener to last position - newListeners[newSize - 1] = listener; - // - // now switch new for old - fStructuredDocumentChangingListeners = newListeners; - // - // when a listener is added, - // send the new model event to that one particular listener, - // so it - // can initialize itself with the current state of the model - // listener.newModel(new NewModelEvent(this, listener)); - } - } - } - - /** - * We manage our own document listners, instead of delegating to our - * parentDocument, so we can fire at very end (and not when the - * parentDocument changes). - * - */ - public void addDocumentListener(IDocumentListener listener) { - synchronized (listenerLock) { - - // make sure listener is not already in listening - // (and if it is, print a warning to aid debugging, if needed) - if (!Utilities.contains(fDocumentListeners, listener)) { - int oldSize = 0; - if (fDocumentListeners != null) { - // normally won't be null, but we need to be sure, for - // first - // time through - oldSize = fDocumentListeners.length; - } - int newSize = oldSize + 1; - IDocumentListener[] newListeners = null; - newListeners = new IDocumentListener[newSize]; - if (fDocumentListeners != null) { - System.arraycopy(fDocumentListeners, 0, newListeners, 0, oldSize); - } - // add listener to last position - newListeners[newSize - 1] = listener; - // now switch new for old - fDocumentListeners = newListeners; - } - } - } - - /* - * @see org.eclipse.jface.text.IDocument#addDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener) - * - * Registers the document partitioning listener with the document. After - * registration the IDocumentPartitioningListener is informed about each - * partition change cause by a document manipulation. If a document - * partitioning listener is also a document listener, the following - * notification sequence is guaranteed if a document manipulation changes - * the document partitioning: 1) - * listener.documentAboutToBeChanged(DocumentEvent); 2) - * listener.documentPartitioningChanged(); 3) - * listener.documentChanged(DocumentEvent); If the listener is already - * registered nothing happens. - * - * @see IDocumentPartitioningListener - */ - - public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) { - synchronized (listenerLock) { - - Assert.isNotNull(listener); - if (fDocumentPartitioningListeners == null) { - fDocumentPartitioningListeners = new ArrayList(1); - } - if (!fDocumentPartitioningListeners.contains(listener)) - fDocumentPartitioningListeners.add(listener); - } - } - - /** - * Adds the position to the document's default position category. The - * default category must be specified by the implementer. A position that - * has been added to a position category is updated at each change applied - * to the document. - * - * @exception BadLocationException - * If position is not a valid range in the document - */ - public void addPosition(Position position) throws BadLocationException { - getPositionManager().addPosition(position); - } - - /** - * @see IDocument#addPosition - * @exception BadLocationException - * If position is not a valid range in the document - * @exception BadPositionCategoryException - * If the category is not defined for the document - */ - public void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException { - getPositionManager().addPosition(category, position); - } - - /** - * @see IDocument#addPositionCategory - */ - public void addPositionCategory(String category) { - internal_addPositionCategory(category); - } - - /** - * @see IDocument#addPositionUpdater - */ - public void addPositionUpdater(IPositionUpdater updater) { - internal_addPositionUpdater(updater); - } - - /** - * Adds the given document listener as one which is notified before those - * document listeners added with <code>addDocumentListener</code> are - * notified. If the given listener is also registered using - * <code>addDocumentListener</code> it will be notified twice. If the - * listener is already registered nothing happens. - * <p> - * - * This method is not for public use, it may only be called by - * implementers of <code>IDocumentAdapter</code> and only if those - * implementers need to implement <code>IDocumentListener</code>. - * - * @param documentAdapter - * the listener to be added as prenotified document listener - */ - public void addPrenotifiedDocumentListener(IDocumentListener documentAdapter) { - synchronized (listenerLock) { - - if (fPrenotifiedDocumentListeners != null) { - int previousSize = fPrenotifiedDocumentListeners.length; - IDocumentListener[] listeners = new IDocumentListener[previousSize + 1]; - System.arraycopy(fPrenotifiedDocumentListeners, 0, listeners, 0, previousSize); - listeners[previousSize] = documentAdapter; - fPrenotifiedDocumentListeners = listeners; - } - else { - fPrenotifiedDocumentListeners = new IDocumentListener[1]; - fPrenotifiedDocumentListeners[0] = documentAdapter; - } - } - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#charAt(int) - */ - public char charAt(int arg0) { - try { - return getChar(0); - } - catch (BadLocationException e) { - throw new IndexOutOfBoundsException(); - } - } - - /** - * This form of the API removes all read only positions, as should be done - * we 'setText' is called. Note: an alternative algorithm may simply - * remove the category (and it would get added back in later, if/when - * readonly regions added. - */ - private void clearReadOnly() { - Position[] positions = null; - try { - positions = getPositions(READ_ONLY_REGIONS_CATEGORY); - } - catch (BadPositionCategoryException e) { - Logger.logException("program error: should never occur", e); //$NON-NLS-1$ - } - for (int i = 0; i < positions.length; i++) { - Position position = positions[i]; - // note we don't fire the "about to change" or "changed" events, - // since presumably, text is all going away and being replaced - // anyway. - position.delete(); - } - } - - - public void clearReadOnly(int startOffset, int length) { - // TODO DW I still need to implement smarter algorithm that - // adust existing RO regions, if needed. For now, I'll just - // remove any that overlap. - try { - Position[] positions = getPositions(READ_ONLY_REGIONS_CATEGORY); - for (int i = 0; i < positions.length; i++) { - Position position = positions[i]; - if (position.overlapsWith(startOffset, length)) { - String effectedText = this.get(startOffset, length); - // fDocumentEvent = new DocumentEvent(this, startOffset, - // length, effectedText); - fireReadOnlyAboutToBeChanged(); - position.delete(); - NoChangeEvent noChangeEvent = new NoChangeEvent(this, null, effectedText, startOffset, length); - noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE; - fireReadOnlyStructuredDocumentEvent(noChangeEvent); - } - } - } - catch (BadPositionCategoryException e) { - // just means no readonly regions been defined yet - // so nothing to do. - } - } - - /** - * Computes the index at which a <code>Position</code> with the - * specified offset would be inserted into the given category. As the - * ordering inside a category only depends on the offset, the index must - * be choosen to be the first of all positions with the same offset. - * - * @param category - * the category in which would be added - * @param offset - * the position offset to be considered - * @return the index into the category - * @exception BadLocationException - * if offset is invalid in this document - * @exception BadPositionCategoryException - * if category is undefined in this document - */ - public int computeIndexInCategory(String category, int offset) throws org.eclipse.jface.text.BadPositionCategoryException, org.eclipse.jface.text.BadLocationException { - return getPositionManager().computeIndexInCategory(category, offset); - } - - /** - * Computes the number of lines in the given text. For a given implementer - * of this interface this method returns the same result as - * <code>set(text); getNumberOfLines()</code>. - * - * @param text - * the text whose number of lines should be computed - * @return the number of lines in the given text - */ - public int computeNumberOfLines(String text) { - return getTracker().computeNumberOfLines(text); - } - - /** - * Computes the partitioning of the given document range using the - * document's partitioner. - * - * @param offset - * the document offset at which the range starts - * @param length - * the length of the document range - * @return a specification of the range's partitioning - * @throws BadLocationException - * @throws BadPartitioningException - */ - public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException { - ITypedRegion[] typedRegions = null; - try { - typedRegions = computePartitioning(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, offset, length, false); - } - catch (BadPartitioningException e) { - // impossible in this context - throw new Error(e); - } - if (typedRegions == null) { - typedRegions = new ITypedRegion[0]; - } - return typedRegions; - } - - - public ITypedRegion[] computePartitioning(String partitioning, int offset, int length, boolean includeZeroLengthPartitions) throws BadLocationException, BadPartitioningException { - if ((0 > offset) || (0 > length) || (offset + length > getLength())) - throw new BadLocationException(); - - IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning); - - if (partitioner instanceof IDocumentPartitionerExtension2) - return ((IDocumentPartitionerExtension2) partitioner).computePartitioning(offset, length, includeZeroLengthPartitions); - else if (partitioner != null) - return partitioner.computePartitioning(offset, length); - else if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning)) - return new TypedRegion[]{new TypedRegion(offset, length, DEFAULT_CONTENT_TYPE)}; - else - throw new BadPartitioningException(); - } - - /** - * @see IDocument#containsPosition - */ - public boolean containsPosition(String category, int offset, int length) { - return getPositionManager().containsPosition(category, offset, length); - } - - /** - * @see IDocument#containsPositionCategory - */ - public boolean containsPositionCategory(String category) { - return getPositionManager().containsPositionCategory(category); - } - - public boolean containsReadOnly(int startOffset, int length) { - boolean result = false; - try { - Position[] positions = getPositions(READ_ONLY_REGIONS_CATEGORY); - for (int i = 0; i < positions.length; i++) { - Position position = positions[i]; - if (position.overlapsWith(startOffset, length)) { - result = true; - break; - } - } - } - catch (BadPositionCategoryException e) { - // just means no readonly regions been defined yet - // so obviously false - result = false; - } - return result; - } - - private void executePostNotificationChanges() { - if (fStoppedCount > 0) - return; - while (fPostNotificationChanges != null) { - List changes = fPostNotificationChanges; - fPostNotificationChanges = null; - Iterator e = changes.iterator(); - while (e.hasNext()) { - RegisteredReplace replace = (RegisteredReplace) e.next(); - replace.fReplace.perform(this, replace.fOwner); - } - } - } - - private void fireDocumentAboutToChanged() { - // most DocumentAboutToBeChanged listeners do not anticipate - // DocumentEvent == null. So make sure documentEvent is not - // null. (this should never happen, yet it does sometimes) - if (fDocumentEvent == null) { - fDocumentEvent = new NullDocumentEvent(); - } - - _fireStructuredDocumentAboutToChange(fStructuredDocumentAboutToChangeListeners); - // Note: the docEvent is created in replaceText API! (or set Text) - _fireDocumentAboutToChange(fPrenotifiedDocumentListeners); - notifyDocumentPartitionersAboutToChange(fDocumentEvent); - _fireDocumentAboutToChange(fDocumentListeners); - } - - /** - * Fires the document partitioning changed notification to all registered - * document partitioning listeners. Uses a robust iterator. - * - * @param event - * the document partitioning changed event - * - * @see IDocumentPartitioningListenerExtension2 - */ - protected void fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent event) { - if (fDocumentPartitioningListeners == null || fDocumentPartitioningListeners.size() == 0) - return; - - List list = new ArrayList(fDocumentPartitioningListeners); - Iterator e = list.iterator(); - while (e.hasNext()) { - IDocumentPartitioningListener l = (IDocumentPartitioningListener) e.next(); - if (l instanceof IDocumentPartitioningListenerExtension2) { - IDocumentPartitioningListenerExtension2 extension2 = (IDocumentPartitioningListenerExtension2) l; - extension2.documentPartitioningChanged(event); - } - else if (l instanceof IDocumentPartitioningListenerExtension) { - IDocumentPartitioningListenerExtension extension = (IDocumentPartitioningListenerExtension) l; - extension.documentPartitioningChanged(this, event.getCoverage()); - } - else { - l.documentPartitioningChanged(this); - } - } - - } - - private void fireReadOnlyAboutToBeChanged() { - _fireStructuredDocumentAboutToChange(fStructuredDocumentAboutToChangeListeners); - // Note: the docEvent is created in replaceText API! (or set Text) - // _fireDocumentAboutToChange(fPrenotifiedDocumentListeners); - // _fireDocumentAboutToChange(fDocumentListeners); - } - - private void fireReadOnlyStructuredDocumentEvent(NoChangeEvent event) { - _fireEvent(fStructuredDocumentChangingListeners, event); - _fireEvent(fStructuredDocumentChangedListeners, event); - // _fireDocumentChanged(fPrenotifiedDocumentListeners, event); - // _fireDocumentChanged(fDocumentListeners, event); - // _clearDocumentEvent(); - } - - private void fireStructuredDocumentEvent(NoChangeEvent event) { - _fireEvent(fStructuredDocumentChangingListeners, event); - _fireEvent(fStructuredDocumentChangedListeners, event); - _fireDocumentChanged(fPrenotifiedDocumentListeners, event); - notifyDocumentPartitionersDocumentChanged(event); - _fireDocumentChanged(fDocumentListeners, event); - _clearDocumentEvent(); - } - - private void fireStructuredDocumentEvent(RegionChangedEvent event) { - _fireEvent(fStructuredDocumentChangingListeners, event); - _fireEvent(fStructuredDocumentChangedListeners, event); - _fireDocumentChanged(fPrenotifiedDocumentListeners, event); - notifyDocumentPartitionersDocumentChanged(event); - _fireDocumentChanged(fDocumentListeners, event); - _clearDocumentEvent(); - } - - private void fireStructuredDocumentEvent(RegionsReplacedEvent event) { - _fireEvent(fStructuredDocumentChangingListeners, event); - _fireEvent(fStructuredDocumentChangedListeners, event); - _fireDocumentChanged(fPrenotifiedDocumentListeners, event); - notifyDocumentPartitionersDocumentChanged(event); - _fireDocumentChanged(fDocumentListeners, event); - _clearDocumentEvent(); - } - - private void fireStructuredDocumentEvent(StructuredDocumentRegionsReplacedEvent event) { - _fireEvent(fStructuredDocumentChangingListeners, event); - _fireEvent(fStructuredDocumentChangedListeners, event); - _fireDocumentChanged(fPrenotifiedDocumentListeners, event); - notifyDocumentPartitionersDocumentChanged(event); - _fireDocumentChanged(fDocumentListeners, event); - _clearDocumentEvent(); - } - - /** - * Returns the document's complete text. - */ - public String get() { - return getStore().get(0, getLength()); - } - - /** - * Returns length characters from the document's text starting from the - * specified position. - * - * @throws BadLocationException - * - * @exception BadLocationException - * If the range is not valid in the document - */ - public String get(int offset, int length) { - String result = null; - int myLength = getLength(); - if (0 > offset) - offset = 0; - if (0 > length) - length = 0; - if (offset + length > myLength) { - // first try adjusting length to fit - int lessLength = myLength - offset; - if ((lessLength >= 0) && (offset + lessLength == myLength)) { - length = lessLength; - } - else { - // second, try offset - int moreOffset = myLength - length; - if ((moreOffset >= 0) && (moreOffset + length == myLength)) { - offset = moreOffset; - } - else { - // can happen if myLength is 0. - // no adjustment possible. - result = new String(); - } - } - - } - if (result == null) { - result = getStore().get(offset, length); - } - return result; - } - - public Object getAdapter(Class adapter) { - return Platform.getAdapterManager().getAdapter(this, adapter); - } - - IStructuredDocumentRegion getCachedDocumentRegion() { - IStructuredDocumentRegion result = null; - if (USE_LOCAL_THREAD) { - result = fCurrentDocumentRegionCache.get(); - } - else { - result = cachedDocumentRegion; - } - return result; - } - - /** - * @see IDocument#getChar - * @exception BadLocationException - * If position is not a valid range in the document - */ - public char getChar(int pos) throws BadLocationException { - char result = 0x00; - try { - result = getStore().get(pos); - } - catch (IndexOutOfBoundsException e) { - throw new BadLocationException(e.getLocalizedMessage()); - } - return result; - } - - /** - * Returns the type of the document partition containing the given - * character position. - */ - public String getContentType(int offset) throws BadLocationException { - return getDocumentPartitioner().getContentType(offset); - } - - - public String getContentType(String partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException { - if ((0 > offset) || (offset > getLength())) - throw new BadLocationException(); - - IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning); - - if (partitioner instanceof IDocumentPartitionerExtension2) - return ((IDocumentPartitionerExtension2) partitioner).getContentType(offset, preferOpenPartitions); - else if (partitioner != null) - return partitioner.getContentType(offset); - else if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning)) - return DEFAULT_CONTENT_TYPE; - else - throw new BadPartitioningException(); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#getDefaultLineDelimiter() - */ - public String getDefaultLineDelimiter() { - - String lineDelimiter= null; - - try { - lineDelimiter= getLineDelimiter(0); - } catch (BadLocationException x) { - } - - if (lineDelimiter != null) - return lineDelimiter; - - if (fInitialLineDelimiter != null) - return fInitialLineDelimiter; - - String sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$ - String[] delimiters= getLegalLineDelimiters(); - Assert.isTrue(delimiters.length > 0); - for (int i= 0; i < delimiters.length; i++) { - if (delimiters[i].equals(sysLineDelimiter)) { - lineDelimiter= sysLineDelimiter; - break; - } - } - - if (lineDelimiter == null) - lineDelimiter= delimiters[0]; - - return lineDelimiter; - - } - - /** - * Returns the document's partitioner. - * - * @see IDocumentPartitioner - */ - public IDocumentPartitioner getDocumentPartitioner() { - return getDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING); - } - - - public IDocumentPartitioner getDocumentPartitioner(String partitioning) { - - IDocumentPartitioner documentPartitioner = null; - if (fDocumentPartitioners != null) { - documentPartitioner = (IDocumentPartitioner) fDocumentPartitioners.get(partitioning); - } - return documentPartitioner; - } - - public EncodingMemento getEncodingMemento() { - return encodingMemento; - } - - public IStructuredDocumentRegion getFirstStructuredDocumentRegion() { - // should we update cachedNode? - // We should to keep consistent philosophy of remembering last - // requested position, - // for efficiency. - setCachedDocumentRegion(firstDocumentRegion); - return firstDocumentRegion; - } - - public IStructuredDocumentRegion getLastStructuredDocumentRegion() { - // should we update cachedNode? - // We should to keep consistent philosophy of remembering last - // requested position, - // for efficiency. - setCachedDocumentRegion(lastDocumentRegion); - return lastDocumentRegion; - } - - /* - * -------------------------- partitions - * ---------------------------------- - */ - public String[] getLegalContentTypes() { - String[] result = null; - try { - result = getLegalContentTypes(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING); - } - catch (BadPartitioningException e) { - // impossible in this context - throw new Error(e); - } - return result; - } - - public String[] getLegalContentTypes(String partitioning) throws BadPartitioningException { - IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning); - if (partitioner != null) - return partitioner.getLegalContentTypes(); - if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning)) - return new String[]{DEFAULT_CONTENT_TYPE}; - throw new BadPartitioningException(); - } - - /* - * ------------------ line delimiter conversion - * --------------------------- - */ - public String[] getLegalLineDelimiters() { - return getTracker().getLegalLineDelimiters(); - } - - /** - * @see IDocument#getLength - */ - public int getLength() { - return getStore().getLength(); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#getLineDelimiter() - */ - public String getLineDelimiter() { - return getDefaultLineDelimiter(); - } - - /** - * Returns the line delimiter of that line - * - * @exception BadLocationException - * If the line number is invalid in the document - */ - public String getLineDelimiter(int line) throws org.eclipse.jface.text.BadLocationException { - return getTracker().getLineDelimiter(line); - } - - /** - * Returns a description of the specified line. The line is described by - * its offset and its length excluding the line's delimiter. - * - * @param line - * the line of interest - * @return a line description - * @exception BadLocationException - * if the line number is invalid in this document - */ - public org.eclipse.jface.text.IRegion getLineInformation(int line) throws org.eclipse.jface.text.BadLocationException { - return getTracker().getLineInformation(line); - } - - /** - * Returns a description of the line at the given offset. The description - * contains the offset and the length of the line excluding the line's - * delimiter. - * - * @param offset - * the offset whose line should be described - * @return a region describing the line - * @exception BadLocationException - * if offset is invalid in this document - */ - public org.eclipse.jface.text.IRegion getLineInformationOfOffset(int offset) throws org.eclipse.jface.text.BadLocationException { - return getTracker().getLineInformationOfOffset(offset); - } - - /* - * ---------------------- line information - * -------------------------------- - */ - public int getLineLength(int line) throws org.eclipse.jface.text.BadLocationException { - return getTracker().getLineLength(line); - } - - /** - * Determines the offset of the first character of the given line. - * - * @param line - * the line of interest - * @return the document offset - * @exception BadLocationException - * if the line number is invalid in this document - */ - public int getLineOffset(int line) throws org.eclipse.jface.text.BadLocationException { - return getTracker().getLineOffset(line); - } - - public int getLineOfOffset(int offset) { - int result = -1; - try { - result = getTracker().getLineNumberOfOffset(offset); - } - catch (BadLocationException e) { - if (Logger.DEBUG_DOCUMENT) - Logger.log(Logger.INFO, "Dev. Program Info Only: IStructuredDocument::getLineOfOffset: offset out of range, zero assumed. offset = " + offset, e); //$NON-NLS-1$ //$NON-NLS-2$ - result = 0; - } - return result; - } - - /** - * Returns the number of lines in this document - * - * @return the number of lines in this document - */ - public int getNumberOfLines() { - return getTracker().getNumberOfLines(); - } - - /** - * Returns the number of lines which are occupied by a given text range. - * - * @param offset - * the offset of the specified text range - * @param length - * the length of the specified text range - * @return the number of lines occupied by the specified range - * @exception BadLocationException - * if specified range is invalid in this tracker - */ - public int getNumberOfLines(int offset, int length) throws org.eclipse.jface.text.BadLocationException { - return getTracker().getNumberOfLines(offset, length); - } - - /** - * This is public, temporarily, for use by tag lib classes. - */ - public RegionParser getParser() { - if (fParser == null) { - throw new IllegalStateException("IStructuredDocument::getParser. Parser needs to be set before use"); //$NON-NLS-1$ - } - return fParser; - } - - /** - * Returns the document partition in which the position is located. The - * partition is specified as typed region. - */ - public ITypedRegion getPartition(int offset) throws BadLocationException { - ITypedRegion partition = null; - try { - partition = getPartition(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, offset, false); - } - catch (BadPartitioningException e) { - throw new Error(e); - } - if (partition == null) { - throw new Error(); - } - return partition; - } - - - public ITypedRegion getPartition(String partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException { - if ((0 > offset) || (offset > getLength())) - throw new BadLocationException(); - ITypedRegion result = null; - - IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning); - - if (partitioner instanceof IDocumentPartitionerExtension2) { - result = ((IDocumentPartitionerExtension2) partitioner).getPartition(offset, preferOpenPartitions); - } - else if (partitioner != null) { - result = partitioner.getPartition(offset); - } - else if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning)) { - result = new TypedRegion(0, getLength(), DEFAULT_CONTENT_TYPE); - } - else - throw new BadPartitioningException(); - return result; - } - - - public String[] getPartitionings() { - if (fDocumentPartitioners == null) - return new String[0]; - String[] partitionings = new String[fDocumentPartitioners.size()]; - fDocumentPartitioners.keySet().toArray(partitionings); - return partitionings; - } - - /** - * Returns all position categories added to this document. - */ - public String[] getPositionCategories() { - return getPositionManager().getPositionCategories(); - } - - /** - * @return Returns the positionManager. - */ - private GenericPositionManager getPositionManager() { - if (fPositionManager == null) { - fPositionManager = new GenericPositionManager(this); - } - return fPositionManager; - } - - /** - * Returns all Positions of the given position category. - * - * @exception BadPositionCategoryException - * If category is not defined for the document - */ - public Position[] getPositions(String category) throws org.eclipse.jface.text.BadPositionCategoryException { - return getPositionManager().getPositions(category); - } - - /** - * @see IDocument#getPositionUpdaters - */ - public IPositionUpdater[] getPositionUpdaters() { - return getPositionManager().getPositionUpdaters(); - } - - /** - * This method can return null, which is the case if the offset is just - * before or just after the existing text. Compare with - * getNodeAtCharacterOffset. - */ - public IStructuredDocumentRegion getRegionAtCharacterOffset(int offset) { - IStructuredDocumentRegion result = null; - - // FIXME: need to synch on 'cachedRegion' (but since that's a - // constantly changing object, we - // can't, so need to add a "region_lock" object, and use it here, and - // in re-parser. - // Oh, and need to make sure, after synch, that the region is not - // deleted, and if so, I guess go back - // to the beginning! - - // cached node can be null when document is empty - IStructuredDocumentRegion potentialCachedRegion = getCachedDocumentRegion(); - if (potentialCachedRegion != null) { - - // - - // if we already have the right node, return that. - if (potentialCachedRegion.containsOffset(offset)) { - result = potentialCachedRegion; - } - else { - // first, find out what direction to go, relative to - // cachedNode. - // negative means "towards the front" of the file, - // postitive - // means - // towards the end. - int direction = offset - potentialCachedRegion.getStart(); - if (direction < 0) { - // search towards beginning - while (!potentialCachedRegion.containsOffset(offset)) { - IStructuredDocumentRegion tempNode = potentialCachedRegion.getPrevious(); - if (tempNode == null) { - break; - } - else { - potentialCachedRegion = tempNode; - } - } - } - else { - // search towards end - // There is a legitamat condition where the - // offset will not be contained in any node, - // which is if the offset is just past the last - // character of text. - // And, we must gaurd against setting cachedNode to - // null! - while (!potentialCachedRegion.containsOffset(offset)) { - IStructuredDocumentRegion tempNode = potentialCachedRegion.getNext(); - if (tempNode == null) - break; - else - potentialCachedRegion = tempNode; - } - } - } - result = potentialCachedRegion; - } - // just to be doubly sure we never assign null to an already valid - // cachedRegion. - // I believe any time 'result' is null at this point, that just means - // we have an - // empty document, and the cachedRegion is already null, but we check - // and print - // warning, just so during development we be sure we never accidently - // break this assumption. - if (result != null) - setCachedDocumentRegion(result); - else if (getCachedDocumentRegion() != null) { - throw new IllegalStateException("Program Error: no region could be found to cache, but cache was non null. Indicates corrupted model or region list"); //$NON-NLS-1$ - } - - return result; - } - - public IStructuredDocumentRegionList getRegionList() { - CoreNodeList result = null; - if (getCachedDocumentRegion() == null) - result = new CoreNodeList(null); - else - result = new CoreNodeList(getFirstStructuredDocumentRegion()); - - return result; - } - - - public IStructuredDocumentRegion[] getStructuredDocumentRegions() { - return getStructuredDocumentRegions(0, getLength()); - } - - /** - * <p> - * In the case of 0 length, the <code>IStructuredDocumentRegion</code> - * at the character offset is returened. In other words, the region to the - * right of the caret is returned. except for at the end of the document, - * then the last region is returned. - * </p> - * <p> - * Otherwise all the regions "inbetween" the indicated range are returned, - * including the regions which overlap the region. - * </p> - * - * <br> - * eg. - * <p> - * <br> - * eg. - * - * <pre> - * <html>[<head></head>]</html> returns <head>,</head> - * </pre> - * <pre> - * <ht[ml><head></he]ad></html> returns <html>,<head>,</head> - * </pre> - * - * <pre> - * <html>[<head></head>]</html> returns <head>,</head> - * </pre> - * <pre> - * <ht[ml><head></he]ad></html> returns <html>,<head>,</head> - * </pre> - * - * </p> - */ - public IStructuredDocumentRegion[] getStructuredDocumentRegions(int start, int length) { - - if (length < 0) - throw new IllegalArgumentException("can't have negative length"); //$NON-NLS-1$ - - // this will make the right edge of the range point into the selection - // eg. <html>[<head></head>]</html> - // will return <head>,</head> instead of <head>,</head>,</html> - if (length > 0) - length--; - - List results = new ArrayList(); - - // start thread safe block - try { - acquireLock(); - - IStructuredDocumentRegion currentRegion = getRegionAtCharacterOffset(start); - IStructuredDocumentRegion endRegion = getRegionAtCharacterOffset(start + length); - while (currentRegion != endRegion && currentRegion != null) { - results.add(currentRegion); - currentRegion = currentRegion.getNext(); - } - // need to add that last end region - // can be null in the case of an empty document - if (endRegion != null) - results.add(endRegion); - } - finally { - releaseLock(); - } - // end thread safe block - - return (IStructuredDocumentRegion[]) results.toArray(new IStructuredDocumentRegion[results.size()]); - } - - /** - * was made public for easier testing. Normally should never be used by - * client codes. - */ - public IStructuredTextReParser getReParser() { - if (fReParser == null) { - fReParser = new StructuredDocumentReParser(); - fReParser.setStructuredDocument(this); - } - return fReParser; - } - - private ITextStore getStore() { - return fStore; - } - - public String getText() { - String result = get(); - return result; - } - - /** - * Returns the document's line tracker. Assumes that the document has been - * initialized with a line tracker. - * - * @return the document's line tracker - */ - private ILineTracker getTracker() { - return fTracker; - } - - public IStructuredTextUndoManager getUndoManager() { - if (fUndoManager == null) { - fUndoManager = new StructuredTextUndoManager(); - } - return fUndoManager; - } - - void initializeFirstAndLastDocumentRegion() { - // cached Node must also be first, at the initial point. Only - // valid - // to call this method right after the first parse. - // - // when starting afresh, our cachedNode should be our firstNode, - // so be sure to initialize the firstNode - firstDocumentRegion = getCachedDocumentRegion(); - // be sure to use 'getNext' for this initial finding of the last - // node, - // since the implementation of node.getLastNode may simply call - // structuredDocument.getLastStructuredDocumentRegion! - IStructuredDocumentRegion aNode = firstDocumentRegion; - if (aNode == null) { - // defect 254607: to handle empty documents right, if - // firstnode is - // null, make sure last node is null too - lastDocumentRegion = null; - } - else { - while (aNode != null) { - lastDocumentRegion = aNode; - aNode = aNode.getNext(); - } - } - } - - /** - * @see IDocument#insertPositionUpdater - */ - public void insertPositionUpdater(IPositionUpdater updater, int index) { - getPositionManager().insertPositionUpdater(updater, index); - } - - private void internal_addPositionCategory(String category) { - getPositionManager().addPositionCategory(category); - } - - private void internal_addPositionUpdater(IPositionUpdater updater) { - getPositionManager().addPositionUpdater(updater); - } - - private void internal_setParser(RegionParser newParser) { - fParser = newParser; - } - - String internalGet(int offset, int length) { - String result = null; - // int myLength = getLength(); - // if ((0 > offset) || (0 > length) || (offset + length > myLength)) - // throw new BadLocationException(); - result = getStore().get(offset, length); - return result; - } - - /** - * @param requester - * @param start - * @param replacementLength - * @param changes - * @param modificationStamp - * @param ignoreReadOnlySettings - * @return - */ - private StructuredDocumentEvent internalReplaceText(Object requester, int start, int replacementLength, String changes, long modificationStamp, boolean ignoreReadOnlySettings) { - StructuredDocumentEvent result = null; - - stopPostNotificationProcessing(); - if (changes == null) - changes = ""; //$NON-NLS-1$ - // - if (Debug.debugStructuredDocument) - System.out.println(getClass().getName() + "::replaceText(" + start + "," + replacementLength + "," + changes + ")"); //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ - if (Debug.perfTestStructuredDocumentOnly || Debug.perfTest || Debug.perfTestRawStructuredDocumentOnly) { - startStreamTime = System.currentTimeMillis(); - } - try { - // Note: event must be computed before 'fire' method called - fDocumentEvent = new DocumentEvent(this, start, replacementLength, changes); - fireDocumentAboutToChanged(); - - try { - acquireLock(); - - if (!ignoreReadOnlySettings && (containsReadOnly(start, replacementLength))) { - NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength); - noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE; - result = noChangeEvent; - } - else { - result = updateModel(requester, start, replacementLength, changes); - } - } - finally { - releaseLock(); - } - - - if (Debug.perfTestRawStructuredDocumentOnly || Debug.perfTest) { - long stopStreamTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t Time for IStructuredDocument raw replaceText: " + (stopStreamTime - startStreamTime)); //$NON-NLS-1$ - } - if (Debug.debugStructuredDocument) { - System.out.println("event type returned by replaceTextWithNoDebuggingThread: " + result); //$NON-NLS-1$ - } - } - finally { - // FUTURE_TO_DO: implement callback mechanism? to avoid instanceof - // and casting - // fireStructuredDocumentEvent must be called in order to end - // documentAboutToBeChanged state - - - // increment modification stamp if modifications were made - if (result != null && !(result instanceof NoChangeEvent)) { - fModificationStamp= modificationStamp; - fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp); - fDocumentEvent.fModificationStamp = fModificationStamp; - } - - if (result == null) { - // result should not be null, but if an exception was thrown, - // it will be - // so send a noChangeEvent and log the problem - NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength); - noChangeEvent.reason = NoChangeEvent.NO_EVENT; - fireStructuredDocumentEvent(noChangeEvent); - Logger.log(Logger.ERROR, "Program Error: invalid structured document event"); //$NON-NLS-1$ - } - else { - if (result instanceof RegionChangedEvent) { - fireStructuredDocumentEvent((RegionChangedEvent) result); - } - else { - if (result instanceof RegionsReplacedEvent) { - fireStructuredDocumentEvent((RegionsReplacedEvent) result); - } - else { - if (result instanceof StructuredDocumentRegionsReplacedEvent) { - // probably more efficient to mark old regions as - // 'deleted' at the time - // that are determined to be deleted, but I'll do - // here - // in then central spot - // for programming ease. - updateDeletedFields((StructuredDocumentRegionsReplacedEvent) result); - fireStructuredDocumentEvent((StructuredDocumentRegionsReplacedEvent) result); - } - else { - if (result instanceof NoChangeEvent) { - fireStructuredDocumentEvent((NoChangeEvent) result); - } - else { - // if here, this means a new event was created - // and not handled here - // just send a no event until this issue is - // resolved. - NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength); - noChangeEvent.reason = NoChangeEvent.NO_EVENT; - fireStructuredDocumentEvent(noChangeEvent); - Logger.log(Logger.INFO, "Program Error: unexpected structured document event: " + result); //$NON-NLS-1$ - } - } - } - } - } - - if (Debug.perfTest || Debug.perfTestStructuredDocumentOnly) { - long stopStreamTime = System.currentTimeMillis(); - System.out.println("\n\t\t\t\t Total Time for IStructuredDocument event signaling/processing in replaceText: " + (stopStreamTime - startStreamTime)); //$NON-NLS-1$ - } - resumePostNotificationProcessing(); - } - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#length() - */ - public int length() { - - return getLength(); - } - - public void makeReadOnly(int startOffset, int length) { - makeReadOnly(startOffset, length, false, false); - } - - public void makeReadOnly(int startOffset, int length, boolean canInsertBefore, boolean canInsertAfter) { - // doesn't make sense to have a readonly region of 0 length, - // so we'll ignore those requests - if (length <= 0) - return; - String affectedText = this.get(startOffset, length); - // a document event for "read only" change ... must - // be followed by "no change" structuredDocument event - // fDocumentEvent = new DocumentEvent(this, startOffset, length, - // affectedText); - fireReadOnlyAboutToBeChanged(); - // if (containsReadOnly(startOffset, length)) { - // adjustReadOnlyRegions(startOffset, length); - // } else { - // we can blindly add category, since no harm done if already - // exists. - addPositionCategory(READ_ONLY_REGIONS_CATEGORY); - Position newPosition = new ReadOnlyPosition(startOffset, length, canInsertBefore); - try { - addPosition(READ_ONLY_REGIONS_CATEGORY, newPosition); - // FIXME: need to change API to pass in requester, so this event - // can be - // created correctly, instead of using null. - NoChangeEvent noChangeEvent = new NoChangeEvent(this, null, affectedText, startOffset, length); - noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE; - fireReadOnlyStructuredDocumentEvent(noChangeEvent); - } - catch (BadLocationException e) { - // for now, log and ignore. Perhaps later we - // could adjust to handle some cases? - Logger.logException(("could not create readonly region at " + startOffset + " to " + length), e); //$NON-NLS-1$ //$NON-NLS-2$ - } - catch (BadPositionCategoryException e) { - // should never occur, since we add category - Logger.logException(e); - } - } - - public IStructuredDocument newInstance() { - IStructuredDocument newInstance = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser().newInstance()); - ((BasicStructuredDocument) newInstance).setReParser(getReParser().newInstance()); - if (getDocumentPartitioner() instanceof StructuredTextPartitioner) { - newInstance.setDocumentPartitioner(((StructuredTextPartitioner) getDocumentPartitioner()).newInstance()); - newInstance.getDocumentPartitioner().connect(newInstance); - } - newInstance.setLineDelimiter(getLineDelimiter()); - if (getEncodingMemento() != null) { - newInstance.setEncodingMemento((EncodingMemento) getEncodingMemento().clone()); - } - return newInstance; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.internal.text.IRegionComparible#regionMatches(int, - * int, java.lang.String) - */ - public boolean regionMatches(int offset, int length, String stringToCompare) { - boolean result = false; - ITextStore store = getStore(); - if (store instanceof IRegionComparible) { - result = ((IRegionComparible) store).regionMatches(offset, length, stringToCompare); - } - else { - result = get(offset, length).equals(stringToCompare); - } - return result; - } - - public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) { - boolean result = false; - ITextStore store = getStore(); - if (store instanceof IRegionComparible) { - result = ((IRegionComparible) store).regionMatchesIgnoreCase(offset, length, stringToCompare); - } - else { - result = get(offset, length).equalsIgnoreCase(stringToCompare); - } - return result; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#registerPostNotificationReplace(org.eclipse.jface.text.IDocumentListener, - * org.eclipse.jface.text.IDocumentExtension.IReplace) - */ - public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) { - if (fAcceptPostNotificationReplaces) { - if (fPostNotificationChanges == null) - fPostNotificationChanges = new ArrayList(1); - fPostNotificationChanges.add(new RegisteredReplace(owner, replace)); - } - } - - protected void releaseLock() { - // do nothing here in super class - } - - public void removeDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) { - synchronized (listenerLock) { - - if ((fStructuredDocumentAboutToChangeListeners != null) && (listener != null)) { - // if its not in the listeners, we'll ignore the request - if (Utilities.contains(fStructuredDocumentAboutToChangeListeners, listener)) { - int oldSize = fStructuredDocumentAboutToChangeListeners.length; - int newSize = oldSize - 1; - Object[] newListeners = new Object[newSize]; - int index = 0; - for (int i = 0; i < oldSize; i++) { - if (fStructuredDocumentAboutToChangeListeners[i] == listener) { // ignore - } - else { - // copy old to new if its not the one we are - // removing - newListeners[index++] = fStructuredDocumentAboutToChangeListeners[i]; - } - } - // now that we have a new array, let's switch it for the - // old - // one - fStructuredDocumentAboutToChangeListeners = newListeners; - } - } - } - } - - /** - * removeModelChangedListener method comment. - */ - public void removeDocumentChangedListener(IStructuredDocumentListener listener) { - synchronized (listenerLock) { - - if ((fStructuredDocumentChangedListeners != null) && (listener != null)) { - // if its not in the listeners, we'll ignore the request - if (Utilities.contains(fStructuredDocumentChangedListeners, listener)) { - int oldSize = fStructuredDocumentChangedListeners.length; - int newSize = oldSize - 1; - Object[] newListeners = new Object[newSize]; - int index = 0; - for (int i = 0; i < oldSize; i++) { - if (fStructuredDocumentChangedListeners[i] == listener) { // ignore - } - else { - // copy old to new if its not the one we are - // removing - newListeners[index++] = fStructuredDocumentChangedListeners[i]; - } - } - // now that we have a new array, let's switch it for the - // old - // one - fStructuredDocumentChangedListeners = newListeners; - } - } - } - } - - public void removeDocumentChangingListener(IStructuredDocumentListener listener) { - synchronized (listenerLock) { - - if ((fStructuredDocumentChangingListeners != null) && (listener != null)) { - // if its not in the listeners, we'll ignore the request - if (Utilities.contains(fStructuredDocumentChangingListeners, listener)) { - int oldSize = fStructuredDocumentChangingListeners.length; - int newSize = oldSize - 1; - Object[] newListeners = new Object[newSize]; - int index = 0; - for (int i = 0; i < oldSize; i++) { - if (fStructuredDocumentChangingListeners[i] == listener) { // ignore - } - else { - // copy old to new if its not the one we are - // removing - newListeners[index++] = fStructuredDocumentChangingListeners[i]; - } - } - // now that we have a new array, let's switch it for the - // old - // one - fStructuredDocumentChangingListeners = newListeners; - } - } - } - } - - public void removeDocumentListener(IDocumentListener listener) { - synchronized (listenerLock) { - - if ((fDocumentListeners != null) && (listener != null)) { - // if its not in the listeners, we'll ignore the request - if (Utilities.contains(fDocumentListeners, listener)) { - int oldSize = fDocumentListeners.length; - int newSize = oldSize - 1; - IDocumentListener[] newListeners = new IDocumentListener[newSize]; - int index = 0; - for (int i = 0; i < oldSize; i++) { - if (fDocumentListeners[i] == listener) { // ignore - } - else { - // copy old to new if its not the one we are - // removing - newListeners[index++] = fDocumentListeners[i]; - } - } - // now that we have a new array, let's switch it for the - // old - // one - fDocumentListeners = newListeners; - } - } - } - } - - /* - * @see org.eclipse.jface.text.IDocument#removeDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener) - */ - public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) { - synchronized (listenerLock) { - - Assert.isNotNull(listener); - if (fDocumentPartitioningListeners != null) - fDocumentPartitioningListeners.remove(listener); - } - } - - /** - * Removes the given <code>Position</code> from the document's default - * position category. The default position category is to be defined by - * the implementers. If the position is not part of the document's default - * category nothing happens. - */ - public void removePosition(Position position) { - getPositionManager().removePosition(position); - } - - /** - * @see IDocument#removePosition - * @exception BadPositionCategoryException - * If the category is not defined for the document - */ - public void removePosition(String category, Position position) throws BadPositionCategoryException { - getPositionManager().removePosition(category, position); - } - - /** - * @see IDocument#removePositionCategory - * @exception BadPositionCategoryException - * If the category is not defined for the document - */ - public void removePositionCategory(String category) throws BadPositionCategoryException { - getPositionManager().removePositionCategory(category); - } - - /** - * @see IDocument#removePositionUpdater - */ - public void removePositionUpdater(IPositionUpdater updater) { - getPositionManager().removePositionUpdater(updater); - } - - /** - * Removes the given document listener from teh document's list of - * prenotified document listeners. If the listener is not registered with - * the document nothing happens. - * <p> - * - * This method is not for public use, it may only be called by - * implementers of <code>IDocumentAdapter</code> and only if those - * implementers need to implement <code>IDocumentListener</code>. - * - * @param documentAdapter - * the listener to be removed - * - * @see #addPrenotifiedDocumentListener(IDocumentListener) - */ - public void removePrenotifiedDocumentListener(org.eclipse.jface.text.IDocumentListener documentAdapter) { - synchronized (listenerLock) { - - if (Utilities.contains(fPrenotifiedDocumentListeners, documentAdapter)) { - int previousSize = fPrenotifiedDocumentListeners.length; - if (previousSize > 1) { - IDocumentListener[] listeners = new IDocumentListener[previousSize - 1]; - int previousIndex = 0; - int newIndex = 0; - while (previousIndex < previousSize) { - if (fPrenotifiedDocumentListeners[previousIndex] != documentAdapter) - listeners[newIndex++] = fPrenotifiedDocumentListeners[previousIndex]; - previousIndex++; - } - fPrenotifiedDocumentListeners = listeners; - } - else { - fPrenotifiedDocumentListeners = null; - } - } - } - } - - /** - * This method is for INTERNAL USE ONLY and is NOT API. - * - * Rebuilds the StructuredDocumentRegion chain from the existing text. - * FileBuffer support does not allow clients to know the document's - * location before the text contents are set. - * - * @see set(String) - */ - public void reparse(Object requester) { - // check if we're already making document-wide changes on this thread - if (fStoppedCount > 0) - return; - - stopPostNotificationProcessing(); - clearReadOnly(); - - try { - acquireLock(); - - CharSequenceReader subSetTextStoreReader = new CharSequenceReader((CharSequence) getStore(), 0, getStore().getLength()); - resetParser(subSetTextStoreReader, 0); - // - setCachedDocumentRegion(getParser().getDocumentRegions()); - // when starting afresh, our cachedNode should be our firstNode, - // so be sure to initialize the firstNode and lastNode - initializeFirstAndLastDocumentRegion(); - StructuredDocumentRegionIterator.setParentDocument(getCachedDocumentRegion(), this); - } - finally { - releaseLock(); - } - - resumePostNotificationProcessing(); - } - - /** - * @see IDocument#replace - * @exception BadLocationException - * If position is not a valid range in the document - */ - public void replace(int offset, int length, String text) throws BadLocationException { - if (Debug.displayWarnings) { - System.out.println("Note: IStructuredDocument::replace(int, int, String) .... its better to use replaceText(source, string, int, int) API for structuredDocument updates"); //$NON-NLS-1$ - } - replaceText(this, offset, length, text); - } - - /** - * Replace the text with "newText" starting at position "start" for a - * length of "replaceLength". - * <p> - * - * @param pos - * start offset of text to replace None of the offsets include - * delimiters of preceeding lines. Offset 0 is the first - * character of the document. - * @param length - * start offset of text to replace - * @param text - * start offset of text to replace - * <p> - * Implementors have to notify TextChanged listeners after the - * content has been updated. The TextChangedEvent should be set - * as follows: - * - * event.type = SWT.TextReplaced event.start = start of the replaced text - * event.numReplacedLines = number of replaced lines event.numNewLines = - * number of new lines event.replacedLength = length of the replaced text - * event.newLength = length of the new text - * - * NOTE: numNewLines is the number of inserted lines and numReplacedLines - * is the number of deleted lines based on the change that occurs - * visually. For example: - * - * replacedText newText numReplacedLines numNewLines "" "\n" 0 1 "\n\n" - * "a" 2 0 "a" "\n\n" 0 2 - */ - /** - * One of the APIs to manipulate the IStructuredDocument in terms of text. - */ - public StructuredDocumentEvent replaceText(Object requester, int pos, int length, String text) { - if (length == 0 && (text == null || text.length() == 0)) - return replaceText(requester, pos, length, text, getModificationStamp(), true); - else - return replaceText(requester, pos, length, text, getNextModificationStamp(), true); - } - - public StructuredDocumentEvent replaceText(Object requester, int start, int replacementLength, String changes, boolean ignoreReadOnlySettings) { - long modificationStamp; - - if (replacementLength == 0 && (changes == null || changes.length() == 0)) - modificationStamp = getModificationStamp(); - else - modificationStamp = getNextModificationStamp(); - - return replaceText(requester, start, replacementLength, changes, modificationStamp, ignoreReadOnlySettings); - } - - private StructuredDocumentEvent replaceText(Object requester, int start, int replacementLength, String changes, long modificationStamp, boolean ignoreReadOnlySettings) { - StructuredDocumentEvent event = internalReplaceText(requester, start, replacementLength, changes, modificationStamp, ignoreReadOnlySettings); - return event; - } - - void resetParser(int startOffset, int endOffset) { - - RegionParser parser = getParser(); - ITextStore textStore = getStore(); - if (textStore instanceof CharSequence) { - CharSequenceReader subSetTextStoreReader = new CharSequenceReader((CharSequence) textStore, startOffset, endOffset - startOffset); - parser.reset(subSetTextStoreReader, startOffset); - } - else { - String newNodeText = get(startOffset, endOffset - startOffset); - parser.reset(newNodeText, startOffset); - - } - - } - - void resetParser(Reader reader, int startOffset) { - RegionParser parser = getParser(); - parser.reset(reader, startOffset); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#resumePostNotificationProcessing() - */ - public void resumePostNotificationProcessing() { - --fStoppedCount; - if (fStoppedCount == 0 && fReentranceCount == 0) - executePostNotificationChanges(); - } - - /** - * @deprecated in superclass in 3.0 - use a FindReplaceDocumentAdapter - * directly - * @see IDocument#search - */ - public int search(int startPosition, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException { - // (dmw) I added this warning, to know if still being used. I'm not - // sure it - // works as expected any longer. - // but the warning should be removed, once know. - Logger.log(Logger.INFO, "WARNING: using unsupported deprecated method 'search'"); //$NON-NLS-1$ - int offset = -1; - IRegion match = new FindReplaceDocumentAdapter(this).find(startPosition, findString, forwardSearch, caseSensitive, wholeWord, false); - if (match != null) { - offset = match.getOffset(); - } - return offset; - } - - /** - * @see IDocument#setText - */ - public void set(String string) { - if (Debug.displayInfo) { - System.out.println("Note: IStructuredDocument::setText(String) .... its better to use setText(source, string) API for structuredDocument updates"); //$NON-NLS-1$ - } - setText(null, string); - } - - /** - * This may be marked public, but should be packaged protected, once - * refactoring is complete (in other words, not for client use). - */ - public void setCachedDocumentRegion(IStructuredDocumentRegion structuredRegion) { - if (USE_LOCAL_THREAD) { - fCurrentDocumentRegionCache.set(structuredRegion); - } - else { - cachedDocumentRegion = structuredRegion; - } - } - - /** - * Sets the document's partitioner. - * - * @see IDocumentPartitioner - */ - public void setDocumentPartitioner(IDocumentPartitioner partitioner) { - setDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING, partitioner); - } - - - public void setDocumentPartitioner(String partitioning, IDocumentPartitioner partitioner) { - if (partitioner == null) { - if (fDocumentPartitioners != null) { - fDocumentPartitioners.remove(partitioning); - if (fDocumentPartitioners.size() == 0) - fDocumentPartitioners = null; - } - } - else { - if (fDocumentPartitioners == null) - fDocumentPartitioners = new HashMap(); - fDocumentPartitioners.put(partitioning, partitioner); - } - DocumentPartitioningChangedEvent event = new DocumentPartitioningChangedEvent(this); - event.setPartitionChange(partitioning, 0, getLength()); - fireDocumentPartitioningChanged(event); - } - - public void setEncodingMemento(EncodingMemento encodingMemento) { - this.encodingMemento = encodingMemento; - } - - void setFirstDocumentRegion(IStructuredDocumentRegion region) { - firstDocumentRegion = region; - - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#setInitialLineDelimiter(java.lang.String) - */ - public void setInitialLineDelimiter(String lineDelimiter) { - // make sure our preferred delimiter is - // one of the legal ones - if (Utilities.containsString(getLegalLineDelimiters(), lineDelimiter)) { - fInitialLineDelimiter= lineDelimiter; - } - else { - if (Logger.DEBUG_DOCUMENT) - Logger.log(Logger.INFO, "Attempt to set linedelimiter to non-legal delimiter"); //$NON-NLS-1$ //$NON-NLS-2$ - fInitialLineDelimiter = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, System.getProperty("line.separator"), new IScopeContext[] { new InstanceScope() });//$NON-NLS-1$ - } - } - - void setLastDocumentRegion(IStructuredDocumentRegion region) { - lastDocumentRegion = region; - - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#setLineDelimiter(java.lang.String) - */ - public void setLineDelimiter(String delimiter) { - setInitialLineDelimiter(delimiter); - } - - /** - * Sets the document's line tracker. Must be called at the beginning of - * the constructor. - * - * @param tracker - * the document's line tracker - */ - private void setLineTracker(ILineTracker tracker) { - Assert.isNotNull(tracker); - fTracker = tracker; - } - - public void setParser(RegionParser newParser) { - internal_setParser(newParser); - } - - /** - * @param positionManager - * The positionManager to set. - */ - // TODO: make private is needed, else remove - void setPositionManager(GenericPositionManager positionManager) { - fPositionManager = positionManager; - } - - /** - * - */ - public void setReParser(IStructuredTextReParser newReParser) { - fReParser = newReParser; - if (fReParser != null) { - fReParser.setStructuredDocument(this); - } - } - - /** - * One of the APIs to manipulate the IStructuredDocument in terms of text. - */ - public StructuredDocumentEvent setText(Object requester, String theString) { - StructuredDocumentEvent result = null; - result = replaceText(requester, 0, getLength(), theString, getNextModificationStamp(), true); - return result; - } - - /** - * Sets the document's text store. Must be called at the beginning of the - * constructor. - * - * @param store - * the document's text store - */ - private void setTextStore(ITextStore store) { - Assert.isNotNull(store); - fStore = store; - } - - public void setUndoManager(IStructuredTextUndoManager undoManager) { - - // if the undo manager has already been set, then - // fail fast, since changing the undo manager will lead - // to unusual results (or at least loss of undo stack). - if (fUndoManager != null && fUndoManager != undoManager) { - throw new IllegalArgumentException("can not change undo manager once its been set"); //$NON-NLS-1$ - } - else { - fUndoManager = undoManager; - } - } - - - /* - * {@inheritDoc} - */ - public void startSequentialRewrite(boolean normalized) { - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#stopPostNotificationProcessing() - */ - public void stopPostNotificationProcessing() { - ++fStoppedCount; - } - - - /* - * {@inheritDoc} - */ - public void stopSequentialRewrite() { - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#subSequence(int, int) - */ - public CharSequence subSequence(int arg0, int arg1) { - return get(arg0, arg1); - } - - /** - * @param result - */ - private void updateDeletedFields(StructuredDocumentRegionsReplacedEvent event) { - IStructuredDocumentRegionList oldRegions = event.getOldStructuredDocumentRegions(); - for (int i = 0; i < oldRegions.getLength(); i++) { - IStructuredDocumentRegion structuredDocumentRegion = oldRegions.item(i); - structuredDocumentRegion.setDeleted(true); - } - - } - - /** - * Called by re-parser. Note: this method may be "public" but should only - * be called by re-parsers in the right circumstances. - */ - public void updateDocumentData(int start, int lengthToReplace, String changes) { - stopPostNotificationProcessing(); - getStore().replace(start, lengthToReplace, changes); - try { - getTracker().replace(start, lengthToReplace, changes); - } - - catch (BadLocationException e) { - // should be impossible here, but will log for now - Logger.logException(e); - } - if (fPositionManager != null) { - fPositionManager.updatePositions(new DocumentEvent(this, start, lengthToReplace, changes)); - } - fModificationStamp++; - fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp); - resumePostNotificationProcessing(); - } - - private StructuredDocumentEvent updateModel(Object requester, int start, int lengthToReplace, String changes) { - StructuredDocumentEvent result = null; - IStructuredTextReParser reParser = getReParser(); - // initialize the IStructuredTextReParser with the standard data - // that's - // always needed - reParser.initialize(requester, start, lengthToReplace, changes); - result = reParser.reparse(); - // if result is null at this point, then there must be an error, since - // even if there - // was no change (either disallow due to readonly, or a person pasted - // the same thing - // they had selected) then a "NoChange" event should have been fired. - Assert.isNotNull(result, "no structuredDocument event was created in IStructuredDocument::updateStructuredDocument"); //$NON-NLS-1$ - return result; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument#getPreferredLineDelimiter() - */ - public String getPreferredLineDelimiter() { - return getDefaultLineDelimiter(); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument#setPreferredLineDelimiter(java.lang.String) - */ - public void setPreferredLineDelimiter(String probableLineDelimiter) { - setInitialLineDelimiter(probableLineDelimiter); - - } - - - /** - * Class which implements the rewritable session for the SSE. - * - */ - static class StructuredDocumentRewriteSession extends DocumentRewriteSession { - - /** - * Creates a new session. - * - * @param sessionType - * the type of this session - */ - protected StructuredDocumentRewriteSession(DocumentRewriteSessionType sessionType) { - super(sessionType); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#startRewriteSession(org.eclipse.jface.text.DocumentRewriteSessionType) - */ - public DocumentRewriteSession startRewriteSession(DocumentRewriteSessionType sessionType) throws IllegalStateException { - // delegate to sub-class, so UI threading is handled correctly - return internalStartRewriteSession(sessionType); - } - - /** - * NOT-API. Final protected so clients may call this method if needed, but - * cannot override. - * - * @param sessionType - * @return - * @throws IllegalStateException - */ - final protected DocumentRewriteSession internalStartRewriteSession(DocumentRewriteSessionType sessionType) throws IllegalStateException { - if (getActiveRewriteSession() != null) - throw new IllegalStateException("already in a rewrite session"); - - DocumentRewriteSession session = new StructuredDocumentRewriteSession(sessionType); - DocumentRewriteSessionEvent event = new DocumentRewriteSessionEvent(this, session, DocumentRewriteSessionEvent.SESSION_START); - fireDocumentRewriteSessionEvent(event); - - ILineTracker tracker = getTracker(); - if (tracker instanceof ILineTrackerExtension) { - ILineTrackerExtension extension = (ILineTrackerExtension) tracker; - extension.startRewriteSession(session); - } - - startRewriteSessionOnPartitioners(session); - - if (DocumentRewriteSessionType.SEQUENTIAL == sessionType) - startSequentialRewrite(false); - else if (DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType) - startSequentialRewrite(true); - - fActiveRewriteSession = session; - return session; - } - - /** - * Starts the given rewrite session. - * - * @param session the rewrite session - * @since 2.0 - */ - final void startRewriteSessionOnPartitioners(DocumentRewriteSession session) { - if (fDocumentPartitioners != null) { - Iterator e= fDocumentPartitioners.values().iterator(); - while (e.hasNext()) { - Object partitioner= e.next(); - if (partitioner instanceof IDocumentPartitionerExtension3) { - IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner; - extension.startRewriteSession(session); - } - } - } - } - - - public void stopRewriteSession(DocumentRewriteSession session) { - // delegate to sub-class, so UI threading is handled correctly - internalStopRewriteSession(session); - } - - /** - * NOT-API. Final protected so clients may call this method if needed, but - * cannot override. - * - * @param session - */ - final protected void internalStopRewriteSession(DocumentRewriteSession session) { - if (fActiveRewriteSession == session) { - DocumentRewriteSessionType sessionType = session.getSessionType(); - if (DocumentRewriteSessionType.SEQUENTIAL == sessionType || DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType) - stopSequentialRewrite(); - - stopRewriteSessionOnPartitioners(session); - - ILineTracker tracker = getTracker(); - if (tracker instanceof ILineTrackerExtension) { - ILineTrackerExtension extension = (ILineTrackerExtension) tracker; - extension.stopRewriteSession(session, get()); - } - - fActiveRewriteSession = null; - DocumentRewriteSessionEvent event = new DocumentRewriteSessionEvent(this, session, DocumentRewriteSessionEvent.SESSION_STOP); - fireDocumentRewriteSessionEvent(event); - } - } - - /** - * Stops the given rewrite session. - * - * @param session the rewrite session - * @since 2.0 - */ - final void stopRewriteSessionOnPartitioners(DocumentRewriteSession session) { - if (fDocumentPartitioners != null) { - DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this); - Iterator e= fDocumentPartitioners.keySet().iterator(); - while (e.hasNext()) { - String partitioning= (String) e.next(); - IDocumentPartitioner partitioner= (IDocumentPartitioner) fDocumentPartitioners.get(partitioning); - if (partitioner instanceof IDocumentPartitionerExtension3) { - IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner; - extension.stopRewriteSession(session); - event.setPartitionChange(partitioning, 0, getLength()); - } - } - if (!event.isEmpty()) - fireDocumentPartitioningChanged(event); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#getActiveRewriteSession() - */ - public DocumentRewriteSession getActiveRewriteSession() { - return fActiveRewriteSession; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#addDocumentRewriteSessionListener(org.eclipse.jface.text.IDocumentRewriteSessionListener) - */ - public void addDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) { - synchronized (listenerLock) { - Assert.isNotNull(listener); - if (fDocumentRewriteSessionListeners == null) { - fDocumentRewriteSessionListeners = new ArrayList(1); - } - if (!fDocumentRewriteSessionListeners.contains(listener)) - fDocumentRewriteSessionListeners.add(listener); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#removeDocumentRewriteSessionListener(org.eclipse.jface.text.IDocumentRewriteSessionListener) - */ - public void removeDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) { - synchronized (listenerLock) { - - Assert.isNotNull(listener); - if (fDocumentRewriteSessionListeners != null) - fDocumentRewriteSessionListeners.remove(listener); - } - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#replace(int, int, - * java.lang.String, long) - */ - public void replace(int offset, int length, String text, long modificationStamp) throws BadLocationException { - replaceText(this, offset, length, text, modificationStamp, true); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#set(java.lang.String, - * long) - */ - public void set(String text, long modificationStamp) { - // bug 151069 - overwrite read only regions when setting entire document - replaceText(null, 0, getLength(), text, modificationStamp, true); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension4#getModificationStamp() - */ - public long getModificationStamp() { - return fModificationStamp; - } - - private long getNextModificationStamp() { - if (fNextModificationStamp == Long.MAX_VALUE || fNextModificationStamp == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP) - fNextModificationStamp= 0; - else - fNextModificationStamp= fNextModificationStamp + 1; - - return fNextModificationStamp; - } - - /** - * Fires an event, as specified, to the associated listeners. - * - * @param event - * The event to fire, either a start or stop event. - */ - private void fireDocumentRewriteSessionEvent(final DocumentRewriteSessionEvent event) { - if (fDocumentRewriteSessionListeners == null || fDocumentRewriteSessionListeners.size() == 0) - return; - - Object[] listeners = fDocumentRewriteSessionListeners.toArray(); - for (int i = 0; i < listeners.length; i++) { - final IDocumentRewriteSessionListener l = (IDocumentRewriteSessionListener) listeners[i]; - SafeRunner.run(new ISafeRunnable() { - public void run() throws Exception { - l.documentRewriteSessionChanged(event); - } - public void handleException(Throwable exception) { - // logged for us - } - }); - } - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java deleted file mode 100644 index 7fba9b36ba..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java +++ /dev/null @@ -1,622 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2010 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * David Carver (Intalio) - bug 300430 - String concatenation - * David Carver (Intalio) - bug 300427 - Comparison of String Objects == or != - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - - - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.wst.sse.core.internal.Logger; -import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; -import org.eclipse.wst.sse.core.internal.util.Assert; -import org.eclipse.wst.sse.core.internal.util.Debug; -import org.eclipse.wst.sse.core.internal.util.Utilities; - - -public class BasicStructuredDocumentRegion implements IStructuredDocumentRegion { - private static final String TEXT_STORE_NOT_ASSIGNED = "text store not assigned yet"; //$NON-NLS-1$ - private static final String UNDEFINED = "org.eclipse.wst.sse.core.structuredDocument.UNDEFINED"; //$NON-NLS-1$ - - private ITextRegionList _regions; - /** - * has this region been removed from its document - */ - private static final byte MASK_IS_DELETED = 1; - /** - * was this region terminated normally - */ - private static final byte MASK_IS_ENDED = 1 << 1; - - private byte fIsDeletedOrEnded = 0; - - /** - * allow a pointer back to this nodes model - */ - private IStructuredDocument fParentDocument; - - protected int fLength; - private IStructuredDocumentRegion next = null; - private IStructuredDocumentRegion previous = null; - protected int start; - - public BasicStructuredDocumentRegion() { - super(); - _regions = new TextRegionListImpl(); - - } - - /** - * Even inside-this class uses of 'regions' should use this method, as - * this is where (soft) memory management/reparsing, etc., will be - * centralized. - */ - private ITextRegionList _getRegions() { - - return _regions; - } - - public void addRegion(ITextRegion aRegion) { - _getRegions().add(aRegion); - } - - public void adjust(int i) { - start += i; - } - - public void adjustLength(int i) { - fLength += i; - } - - public void adjustStart(int i) { - start += i; - } - - public void adjustTextLength(int i) { - // not supported - - } - - public boolean containsOffset(int i) { - - return getStartOffset() <= i && i < getEndOffset(); - } - - public boolean containsOffset(ITextRegion containedRegion, int offset) { - return getStartOffset(containedRegion) <= offset && offset < getEndOffset(containedRegion); - } - - public void equatePositions(ITextRegion region) { - start = region.getStart(); - fLength = region.getLength(); - } - - /** - * getEnd and getEndOffset are the same only for - * IStructuredDocumentRegions - */ - public int getEnd() { - return start + fLength; - } - - /** - * getEnd and getEndOffset are the same only for - * IStructuredDocumentRegions - */ - public int getEndOffset() { - return getEnd(); - } - - public int getEndOffset(ITextRegion containedRegion) { - return getStartOffset(containedRegion) + containedRegion.getLength(); - } - - public ITextRegion getFirstRegion() { - if (_getRegions() == null) - return null; - return _getRegions().get(0); - } - - public String getFullText() { - String result = ""; //$NON-NLS-1$ - try { - result = getParentDocument().get(start, fLength); - } - catch (BadLocationException e) { - // log for now, unless we find reason not to - Logger.log(Logger.INFO, e.getMessage()); - } - return result; - } - - public String getFullText(ITextRegion aRegion) { - String result = ""; //$NON-NLS-1$ - try { - int regionStart = aRegion.getStart(); - int regionLength = aRegion.getLength(); - result = fParentDocument.get(start + regionStart, regionLength); - } - catch (BadLocationException e) { - // log for now, unless we find reason not to - Logger.log(Logger.INFO, e.getMessage()); - } - return result; - } - - public String getFullText(String context) { - // DMW: looping is faster than enumeration, - // so switched around 2/12/03 - // Enumeration e = getRegions().elements(); - ITextRegion region = null; - String result = ""; //$NON-NLS-1$ - int length = getRegions().size(); - StringBuffer sb = new StringBuffer(result); - for (int i = 0; i < length; i++) { - region = getRegions().get(i); - if (region.getType().equals(context)) - sb.append(getFullText(region)); - } - result = sb.toString(); - return result; - } - - public ITextRegion getLastRegion() { - if (_getRegions() == null) - return null; - return _getRegions().get(_getRegions().size() - 1); - } - - public int getLength() { - return fLength; - } - - public IStructuredDocumentRegion getNext() { - return next; - } - - public int getNumberOfRegions() { - return _getRegions().size(); - } - - public IStructuredDocument getParentDocument() { - - return fParentDocument; - } - - public IStructuredDocumentRegion getPrevious() { - return previous; - } - - /** - * The parameter offset refers to the overall offset in the document. - */ - public ITextRegion getRegionAtCharacterOffset(int offset) { - if (_getRegions() != null) { - int thisStartOffset = getStartOffset(); - if (offset < thisStartOffset) - return null; - int thisEndOffset = getStartOffset() + getLength(); - if (offset > thisEndOffset) - return null; - // transform the requested offset to the "scale" that - // regions are stored in, which are all relative to the - // start point. - // int transformedOffset = offset - getStartOffset(); - // - ITextRegionList regions = getRegions(); - int length = regions.size(); - int low = 0; - int high = length; - int mid = 0; - // Binary search for the region - while (low < high) { - mid = low + ((high - low) >> 1); - ITextRegion region = regions.get(mid); - if (Debug.debugStructuredDocument) { - System.out.println("region(s) in IStructuredDocumentRegion::getRegionAtCharacterOffset: " + region); //$NON-NLS-1$ - System.out.println(" requested offset: " + offset); //$NON-NLS-1$ - // System.out.println(" transformedOffset: " + - // transformedOffset); //$NON-NLS-1$ - System.out.println(" region start: " + region.getStart()); //$NON-NLS-1$ - System.out.println(" region end: " + region.getEnd()); //$NON-NLS-1$ - System.out.println(" region type: " + region.getType()); //$NON-NLS-1$ - System.out.println(" region class: " + region.getClass()); //$NON-NLS-1$ - - } - // Region is before this one - if (offset < region.getStart() + thisStartOffset) - high = mid; - else if (offset > (region.getEnd() + thisStartOffset - 1)) - low = mid + 1; - else - return region; - } - } - return null; - } - - public ITextRegionList getRegions() { - return _getRegions(); - } - - /** - * getStart and getStartOffset are the same only for - * IStrucutredDocumentRegions - */ - public int getStart() { - return start; - } - - /** - * getStart and getStartOffset are the same only for - * IStrucutredDocumentRegions - */ - public int getStartOffset() { - return getStart(); - } - - public int getStartOffset(ITextRegion containedRegion) { - // assert: containedRegion can not be null - // (might be performance hit if literally put in assert call, - // but containedRegion can not be null). Needs to be checked - // by calling code. - return getStartOffset() + containedRegion.getStart(); - } - - public String getText() { - String result = null; - try { - if (fParentDocument == null) { - // likely to happen during inspecting - result = TEXT_STORE_NOT_ASSIGNED; - } - else { - result = fParentDocument.get(start, fLength); - } - } - catch (BadLocationException e) { - // log for now, unless we find reason not to - Logger.log(Logger.INFO, e.getMessage()); - } - return result; - } - - public String getText(ITextRegion aRegion) { - // assert: aRegion can not be null - // (might be performance hit if literally put in assert call, - // but aRegion can not be null). Needs to be checked - // by calling code. - try { - return fParentDocument.get(this.getStartOffset(aRegion), aRegion.getTextLength()); - } - catch (BadLocationException e) { - Logger.logException(e); - } - return ""; //$NON-NLS-1$ - } - - /** - * Returns the text of the first region with the matching context type - */ - public String getText(String context) { - // DMW: looping is faster than enumeration, - // so switched around 2/12/03 - // Enumeration e = getRegions().elements(); - ITextRegion region = null; - String result = ""; //$NON-NLS-1$ - int length = getRegions().size(); - for (int i = 0; i < length; i++) { - region = getRegions().get(i); - if (region.getType().equals(context)) { - result = getText(region); - break; - } - } - return result; - } - - public int getTextEnd() { - return start + fLength; - } - - /** - * @return int - */ - public int getTextEndOffset() { - ITextRegion region = _getRegions().get(_getRegions().size() - 1); - return getStartOffset() + region.getTextEnd(); - } - - public int getTextEndOffset(ITextRegion containedRegion) { - return getStartOffset(containedRegion) + containedRegion.getTextLength(); - } - - public int getTextLength() { - return fLength; - } - - /** - * Provides the type of IStructuredDocumentRegion ... not to be confused - * with type of XML node! This is subclassed, if something other than type - * of first region is desired. - * - */ - public String getType() { - String result = UNDEFINED; - ITextRegionList subregions = getRegions(); - if (subregions != null && subregions.size() > 0) { - ITextRegion firstRegion = subregions.get(0); - if (firstRegion != null) { - result = firstRegion.getType(); - } - } - return result; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#isDeleted() - */ - public boolean isDeleted() { - return (fIsDeletedOrEnded & MASK_IS_DELETED) != 0 || (fParentDocument == null); - } - - /** - * - * @return boolean - */ - public boolean isEnded() { - return (fIsDeletedOrEnded & MASK_IS_ENDED) != 0; - } - - public boolean sameAs(IStructuredDocumentRegion region, int shift) { - boolean result = false; - // if region == null, we return false; - if (region != null) { - // if the regions are the same instance, they are equal - if (this == region) { - result = true; - } - else { - // this is the non-trivial part - // note: we change for type first, then start offset and end - // offset, - // since that would decide many cases right away and avoid the - // text comparison - if (getType().equals(region.getType())) { - if (sameOffsetsAs(region, shift) && sameTextAs(region, shift)) { - result = true; - } - } - - } - } - return result; - } - - public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion newDocumentRegion, ITextRegion newRegion, int shift) { - boolean result = false; - // if any region is null, we return false (even if both are!) - if ((oldRegion != null) && (newRegion != null)) { - // if the regions are the same instance, they are equal - if (oldRegion == newRegion) { - result = true; - } - else { - // this is the non-trivial part - // note: we change for type first, then start offset and end - // offset, - // since that would decide many cases right away and avoid the - // text comparison - if (oldRegion.getType().equals(newRegion.getType())) { - if (sameOffsetsAs(oldRegion, newDocumentRegion, newRegion, shift)) { - if (sameTextAs(oldRegion, newDocumentRegion, newRegion, shift)) { - result = true; - } - } - } - } - - } - - return result; - } - - private boolean sameOffsetsAs(IStructuredDocumentRegion region, int shift) { - if (getStartOffset() == region.getStartOffset() - shift) { - if (getEndOffset() == region.getEndOffset() - shift) { - return true; - } - } - return false; - } - - private boolean sameOffsetsAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) { - if (getStartOffset(oldRegion) == documentRegion.getStartOffset(newRegion) - shift) { - if (getEndOffset(oldRegion) == documentRegion.getEndOffset(newRegion) - shift) { - return true; - } - } - return false; - } - - private boolean sameTextAs(IStructuredDocumentRegion region, int shift) { - boolean result = false; - try { - if (getText().equals(region.getText())) { - result = true; - } - } - // ISSUE: we should not need this - catch (StringIndexOutOfBoundsException e) { - result = false; - } - - return result; - } - - private boolean sameTextAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) { - boolean result = false; - - if (getText(oldRegion).equals(documentRegion.getText(newRegion))) { - result = true; - } - - return result; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#setDelete(boolean) - */ - public void setDeleted(boolean isDeleted) { - if (isDeleted) - fIsDeletedOrEnded |= MASK_IS_DELETED; - else - fIsDeletedOrEnded &= ~MASK_IS_DELETED; - } - - /** - * - * @param newHasEnd - * boolean - */ - public void setEnded(boolean newHasEnd) { - if (newHasEnd) - fIsDeletedOrEnded |= MASK_IS_ENDED; - else - fIsDeletedOrEnded &= ~MASK_IS_ENDED; - } - - public void setLength(int newLength) { - // textLength = newLength; - fLength = newLength; - } - - public void setNext(IStructuredDocumentRegion newNext) { - next = newNext; - } - - public void setParentDocument(IStructuredDocument document) { - fParentDocument = document; - - } - - public void setPrevious(IStructuredDocumentRegion newPrevious) { - previous = newPrevious; - } - - public void setRegions(ITextRegionList containedRegions) { - _regions = containedRegions; - } - - public void setStart(int newStart) { - start = newStart; - } - - public String toString() { - // NOTE: if the document held by any region has been updated and the - // region offsets have not - // yet been updated, the output from this method invalid. - // Also note, this method can not be changed, without "breaking" - // unit tests, since some of them compare current results to previous - // results. - String result = null; - result = "[" + getStart() + ", " + getEnd() + "] (" + getText() + ")"; //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$ - return result; - } - - private void updateDownStreamRegions(ITextRegion changedRegion, int lengthDifference) { - int listLength = _getRegions().size(); - int startIndex = 0; - // first, loop through to find index of where to start - for (int i = 0; i < listLength; i++) { - ITextRegion region = _getRegions().get(i); - if (region == changedRegion) { - startIndex = i; - break; - } - } - // now, beginning one past the one that was changed, loop - // through to end of list, adjusting the start postions. - startIndex++; - for (int j = startIndex; j < listLength; j++) { - ITextRegion region = _getRegions().get(j); - region.adjustStart(lengthDifference); - } - } - - public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion structuredDocumentRegion, String changes, int requestStart, int lengthToReplace) { - StructuredDocumentEvent result = null; - int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace); - // Get the region pointed to by the requestStart postion, and give - // that region a chance to effect - // the update. - ITextRegion region = getRegionAtCharacterOffset(requestStart); - // if there is no region, then the requested changes must come right - // after the - // node (and right after the last region). This happens, for example, - // when someone - // types something at the end of the document, or more commonly, when - // they are right - // at the beginning of one node, and the dirty start is therefore - // calculated to be the - // previous node. - // So, in this case, we'll give the last region a chance to see if it - // wants to - // swallow the requested changes -- but only for inserts -- deletes - // and "replaces" - // should be reparsed if they are in these border regions, and only if - // the - if ((region == null) && (lengthToReplace == 0)) { - region = _getRegions().get(_getRegions().size() - 1); - // make sure the region is contiguous - if (getEndOffset(region) == requestStart) { - result = region.updateRegion(requester, this, changes, requestStart, lengthToReplace); - } - } - else { - if (region != null) { - // - // If the requested change spans more than one region, then - // we don't give the region a chance to update. - if ((containsOffset(region, requestStart)) && (containsOffset(region, requestStart + lengthToReplace))) { - result = region.updateRegion(requester, this, changes, requestStart, lengthToReplace); - } - } - } - // if result is not null, then we need to update the start and end - // postions of the regions that follow this one - // if result is null, then apply the flatnode specific checks on what - // it can change - // (i.e. more than one region, but no change to the node itself) - if (result != null) { - // That is, a region decided it could handle the change and - // created - // a region changed event. - Assert.isTrue(result instanceof RegionChangedEvent, "Program Error"); //$NON-NLS-1$ - updateDownStreamRegions(((RegionChangedEvent) result).getRegion(), lengthDifference); - // PLUS, we need to update our own node end point (length) - setLength(getLength() + lengthDifference); - } - - return result; - } - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CharSequenceReader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CharSequenceReader.java deleted file mode 100644 index 6ab29b5549..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CharSequenceReader.java +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2004 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import java.io.IOException; -import java.io.Reader; - -public class CharSequenceReader extends Reader { - private int fCurrentPosition; - private int fMaximumReadOffset; - - private CharSequence fOriginalSource; - - /** - * - */ - CharSequenceReader() { - super(); - } - - - public CharSequenceReader(CharSequence originalSource, int offset, int length) { - // ISSUE: should we "fail fast" if requested length is more than there - // is? - fOriginalSource = originalSource; - int startOffset = offset; - int maxRequestedOffset = startOffset + length; - int maxPossibleOffset = 0 + originalSource.length(); - fMaximumReadOffset = Math.min(maxRequestedOffset, maxPossibleOffset); - - fCurrentPosition = startOffset; - - } - - /** - * @param lockObject - */ - CharSequenceReader(Object lockObject) { - super(lockObject); - // for thread safety, may need to add back locking mechanism - // in our custom constructor. This constructor left here just - // for a reminder. - } - - public void close() throws IOException { - // nothing to do when we close - // (may be to eventually "unlock" or null out some varibles - // just for hygene. - // or, perhaps if already closed once throw IOException? for - // consistency? - } - - /** - * @return Returns the originalSource. - * @deprecated - only temporarily public, should be 'default' eventually - * or go away altogether. - */ - public CharSequence getOriginalSource() { - return fOriginalSource; - } - - public int read() { - int result = -1; - if (fCurrentPosition < fMaximumReadOffset) { - result = fOriginalSource.charAt(fCurrentPosition++); - } - return result; - } - - /** - * Read characters into a portion of an array. This method will block - * until some input is available, an I/O error occurs, or the end of the - * stream is reached. - * - * @param cbuf - * Destination buffer - * @param off - * Offset at which to start storing characters - * @param len - * Maximum number of characters to read - * - * @return The number of characters read, or -1 if the end of the stream - * has been reached - * - * @exception IOException - * If an I/O error occurs - */ - - public int read(char[] cbuf, int off, int len) throws IOException { - int charsToRead = -1; - // if already over max, just return -1 - // remember, currentPosition is what is getting ready to be read - // (that is, its already been incremented in read()). - if (fCurrentPosition < fMaximumReadOffset) { - - - int buffMaxToRead = cbuf.length - off; - int minRequested = Math.min(buffMaxToRead, len); - int lengthRemaining = fMaximumReadOffset - fCurrentPosition; - charsToRead = Math.min(minRequested, lengthRemaining); - - - CharSequence seq = fOriginalSource.subSequence(fCurrentPosition, fCurrentPosition + charsToRead); - // for now, hard assumption that original is a String since source - // is assumed to be document, or text store - String seqString = (String) seq; - seqString.getChars(0, seqString.length(), cbuf, off); - - - - fCurrentPosition = fCurrentPosition + charsToRead; - - - } - return charsToRead; - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CoreNodeList.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CoreNodeList.java deleted file mode 100644 index 6acd927143..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CoreNodeList.java +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - - - -import java.util.Enumeration; - -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList; - - -public class CoreNodeList implements IStructuredDocumentRegionList { - int countedLength; - int currentIndex = -1; - - IStructuredDocumentRegion[] flatNodes; - IStructuredDocumentRegion head; - - /** - * CoreNodeList constructor comment. - */ - public CoreNodeList() { - super(); - // create an array, even if zero length - flatNodes = new IStructuredDocumentRegion[0]; - } - - public CoreNodeList(IStructuredDocumentRegion newHead) { - super(); - // save head - head = newHead; - int count = 0; - IStructuredDocumentRegion countNode = newHead; - // we have to go through the list once, to get its - // length in order to create the array - while (countNode != null) { - count++; - countNode = countNode.getNext(); - } - // create an array, even if zero length - flatNodes = new IStructuredDocumentRegion[count]; - // start countNode over again, so to speak. - countNode = newHead; - count = 0; - while (countNode != null) { - flatNodes[count++] = countNode; - countNode = countNode.getNext(); - } - if (count > 0) { - currentIndex = 0; - // else it stays at -1 initialized at object creation - // - // save length - countedLength = count; - } - } - - public CoreNodeList(IStructuredDocumentRegion start, IStructuredDocumentRegion end) { - super(); - // save head - head = start; - int count = 0; - IStructuredDocumentRegion countNode = start; - if ((start == null) || (end == null)) { - // error condition - //throw new IllegalArgumentException("Must provide start and end - // nodes to construct CoreNodeList"); - } else { - count = 1; - while ((countNode != null) && (countNode != end)) { - count++; - countNode = countNode.getNext(); - } - } - // if we ended because the last one was null, - // backup one. - if (countNode == null) - count--; - if (count < 0) { - count = 0; - } - flatNodes = new IStructuredDocumentRegion[count]; - if (count > 0) { - flatNodes[0] = countNode = start; - for (int i = 1; i < count; i++) { - flatNodes[i] = flatNodes[i - 1].getNext(); - } - - } - currentIndex = 0; - countedLength = count; - } - - public Enumeration elements() { - StructuredDocumentRegionEnumeration result = null; - if ((flatNodes != null) && (flatNodes.length > 0)) - result = new StructuredDocumentRegionEnumeration(flatNodes[0], flatNodes[flatNodes.length - 1]); - else - result = new StructuredDocumentRegionEnumeration(null); - return result; - } - - public int getLength() { - return flatNodes.length; - } - - public boolean includes(Object o) { - if (flatNodes == null) - return false; - for (int i = 0; i < flatNodes.length; i++) - if (flatNodes[i] == o) - return true; - return false; - } - - public IStructuredDocumentRegion item(int i) { - return flatNodes[i]; - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/DeleteEqualPositionUpdater.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/DeleteEqualPositionUpdater.java deleted file mode 100644 index e33783e542..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/DeleteEqualPositionUpdater.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import org.eclipse.jface.text.BadPositionCategoryException; -import org.eclipse.jface.text.DefaultPositionUpdater; - -/** - * Follows the behavior of DefaultPositionUpdater except in addition to - * deleting/overwriting text which completely contains the position deletes - * the position, deleting text that equals the text in position also deletes - * the position. - * - * @see org.eclipse.jface.text.DefaultPositionUpdater - */ -public class DeleteEqualPositionUpdater extends DefaultPositionUpdater { - - /** - * @param category - */ - public DeleteEqualPositionUpdater(String category) { - super(category); - } - - /** - * Determines whether the currently investigated position has been deleted - * by the replace operation specified in the current event. If so, it - * deletes the position and removes it from the document's position - * category. - * - * NOTE: position is deleted if current event completely overwrites - * position OR if current event deletes the area surrounding/including the - * position - * - * @return <code>true</code> if position has been deleted - */ - protected boolean notDeleted() { - // position is deleted if current event completely overwrites position - // OR if - // current event deletes the area surrounding/including the position - if ((fOffset < fPosition.offset && (fPosition.offset + fPosition.length < fOffset + fLength)) || (fOffset <= fPosition.offset && (fPosition.offset + fPosition.length <= fOffset + fLength) && fReplaceLength == 0)) { - - fPosition.delete(); - - try { - fDocument.removePosition(getCategory(), fPosition); - } catch (BadPositionCategoryException x) { - } - - return false; - } - - return true; - } - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/GenericPositionManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/GenericPositionManager.java deleted file mode 100644 index 0a422a3835..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/GenericPositionManager.java +++ /dev/null @@ -1,409 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2008 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ - -package org.eclipse.wst.sse.core.internal.text; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.BadPositionCategoryException; -import org.eclipse.jface.text.DefaultPositionUpdater; -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IPositionUpdater; -import org.eclipse.jface.text.Position; -import org.eclipse.wst.sse.core.internal.util.Assert; - -/** - * Based on the Position management methods from - * org.eclipse.jface.text.AbstractDocument - */ - -public class GenericPositionManager { - private CharSequence fCharSequence; - - - - private Map fPositions; - /** All registered document position updaters */ - private List fPositionUpdaters; - - /** - * don't allow instantiation with out document pointer - * - */ - private GenericPositionManager() { - super(); - } - - /** - * - */ - public GenericPositionManager(CharSequence charSequence) { - this(); - // we only use charSequence for "length", to - // made more generic than "document" even "text store" - fCharSequence = charSequence; - completeInitialization(); - } - - /* - * @see org.eclipse.jface.text.IDocument#addPosition(org.eclipse.jface.text.Position) - */ - public void addPosition(Position position) throws BadLocationException { - try { - addPosition(IDocument.DEFAULT_CATEGORY, position); - } - catch (BadPositionCategoryException e) { - } - } - - - - /* - * @see org.eclipse.jface.text.IDocument#addPosition(java.lang.String, - * org.eclipse.jface.text.Position) - */ - public synchronized void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException { - - if ((0 > position.offset) || (0 > position.length) || (position.offset + position.length > getDocumentLength())) - throw new BadLocationException(); - - if (category == null) - throw new BadPositionCategoryException(); - - List list = (List) fPositions.get(category); - if (list == null) - throw new BadPositionCategoryException(); - - list.add(computeIndexInPositionList(list, position.offset), position); - } - - /* - * @see org.eclipse.jface.text.IDocument#addPositionCategory(java.lang.String) - */ - public void addPositionCategory(String category) { - - if (category == null) - return; - - if (!containsPositionCategory(category)) - fPositions.put(category, new ArrayList()); - } - - /* - * @see org.eclipse.jface.text.IDocument#addPositionUpdater(org.eclipse.jface.text.IPositionUpdater) - */ - public void addPositionUpdater(IPositionUpdater updater) { - insertPositionUpdater(updater, fPositionUpdaters.size()); - } - - - /** - * Initializes document listeners, positions, and position updaters. Must - * be called inside the constructor after the implementation plug-ins have - * been set. - */ - protected void completeInitialization() { - - fPositions = new HashMap(); - fPositionUpdaters = new ArrayList(); - - addPositionCategory(IDocument.DEFAULT_CATEGORY); - addPositionUpdater(new DefaultPositionUpdater(IDocument.DEFAULT_CATEGORY)); - } - - /* - * @see org.eclipse.jface.text.IDocument#computeIndexInCategory(java.lang.String, - * int) - */ - public int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException { - - if (0 > offset || offset > getDocumentLength()) - throw new BadLocationException(); - - List c = (List) fPositions.get(category); - if (c == null) - throw new BadPositionCategoryException(); - - return computeIndexInPositionList(c, offset); - } - - - /** - * Computes the index in the list of positions at which a position with - * the given offset would be inserted. The position is supposed to become - * the first in this list of all positions with the same offset. - * - * @param positions - * the list in which the index is computed - * @param offset - * the offset for which the index is computed - * @return the computed index - * - * @see IDocument#computeIndexInCategory(String, int) - */ - protected synchronized int computeIndexInPositionList(List positions, int offset) { - - if (positions.size() == 0) - return 0; - - int left = 0; - int right = positions.size() - 1; - int mid = 0; - Position p = null; - - while (left < right) { - - mid = (left + right) / 2; - - p = (Position) positions.get(mid); - if (offset < p.getOffset()) { - if (left == mid) - right = left; - else - right = mid - 1; - } - else if (offset > p.getOffset()) { - if (right == mid) - left = right; - else - left = mid + 1; - } - else if (offset == p.getOffset()) { - left = right = mid; - } - - } - - int pos = left; - p = (Position) positions.get(pos); - if (offset > p.getOffset()) { - // append to the end - pos++; - } - else { - // entry will became the first of all entries with the same - // offset - do { - --pos; - if (pos < 0) - break; - p = (Position) positions.get(pos); - } - while (offset == p.getOffset()); - ++pos; - } - - Assert.isTrue(0 <= pos && pos <= positions.size()); - - return pos; - } - - /* - * @see org.eclipse.jface.text.IDocument#containsPosition(java.lang.String, - * int, int) - */ - public boolean containsPosition(String category, int offset, int length) { - - if (category == null) - return false; - - List list = (List) fPositions.get(category); - if (list == null) - return false; - - int size = list.size(); - if (size == 0) - return false; - - int index = computeIndexInPositionList(list, offset); - if (index < size) { - Position p = (Position) list.get(index); - while (p != null && p.offset == offset) { - if (p.length == length) - return true; - ++index; - p = (index < size) ? (Position) list.get(index) : null; - } - } - - return false; - } - - /* - * @see org.eclipse.jface.text.IDocument#containsPositionCategory(java.lang.String) - */ - public boolean containsPositionCategory(String category) { - if (category != null) - return fPositions.containsKey(category); - return false; - } - - - - public int getDocumentLength() { - return fCharSequence.length(); - } - - /** - * Returns all positions managed by the document grouped by category. - * - * @return the document's positions - */ - protected Map getDocumentManagedPositions() { - return fPositions; - } - - /* - * @see org.eclipse.jface.text.IDocument#getPositionCategories() - */ - public String[] getPositionCategories() { - String[] categories = new String[fPositions.size()]; - Iterator keys = fPositions.keySet().iterator(); - for (int i = 0; i < categories.length; i++) - categories[i] = (String) keys.next(); - return categories; - } - - - public Position[] getPositions(String category) throws BadPositionCategoryException { - - if (category == null) - throw new BadPositionCategoryException(); - - List c = (List) fPositions.get(category); - if (c == null) - throw new BadPositionCategoryException(); - - Position[] positions = new Position[c.size()]; - c.toArray(positions); - return positions; - } - - /* - * @see org.eclipse.jface.text.IDocument#getPositionUpdaters() - */ - public IPositionUpdater[] getPositionUpdaters() { - IPositionUpdater[] updaters = new IPositionUpdater[fPositionUpdaters.size()]; - fPositionUpdaters.toArray(updaters); - return updaters; - } - - - - /* - * @see org.eclipse.jface.text.IDocument#insertPositionUpdater(org.eclipse.jface.text.IPositionUpdater, - * int) - */ - public synchronized void insertPositionUpdater(IPositionUpdater updater, int index) { - - for (int i = fPositionUpdaters.size() - 1; i >= 0; i--) { - if (fPositionUpdaters.get(i) == updater) - return; - } - - if (index == fPositionUpdaters.size()) - fPositionUpdaters.add(updater); - else - fPositionUpdaters.add(index, updater); - } - - /* - * @see org.eclipse.jface.text.IDocument#removePosition(org.eclipse.jface.text.Position) - */ - public void removePosition(Position position) { - try { - removePosition(IDocument.DEFAULT_CATEGORY, position); - } - catch (BadPositionCategoryException e) { - } - } - - /* - * @see org.eclipse.jface.text.IDocument#removePosition(java.lang.String, - * org.eclipse.jface.text.Position) - */ - public synchronized void removePosition(String category, Position position) throws BadPositionCategoryException { - - if (position == null) - return; - - if (category == null) - throw new BadPositionCategoryException(); - - List c = (List) fPositions.get(category); - if (c == null) - throw new BadPositionCategoryException(); - - // remove based on identity not equality - int size = c.size(); - for (int i = 0; i < size; i++) { - if (position == c.get(i)) { - c.remove(i); - return; - } - } - } - - /* - * @see org.eclipse.jface.text.IDocument#removePositionCategory(java.lang.String) - */ - public void removePositionCategory(String category) throws BadPositionCategoryException { - - if (category == null) - return; - - if (!containsPositionCategory(category)) - throw new BadPositionCategoryException(); - - fPositions.remove(category); - } - - /* - * @see org.eclipse.jface.text.IDocument#removePositionUpdater(org.eclipse.jface.text.IPositionUpdater) - */ - public synchronized void removePositionUpdater(IPositionUpdater updater) { - for (int i = fPositionUpdaters.size() - 1; i >= 0; i--) { - if (fPositionUpdaters.get(i) == updater) { - fPositionUpdaters.remove(i); - return; - } - } - } - - - /** - * Updates all positions of all categories to the change described by the - * document event. All registered document updaters are called in the - * sequence they have been arranged. Uses a robust iterator. - * - * @param event - * the document event describing the change to which to adapt - * the positions - */ - protected synchronized void updatePositions(DocumentEvent event) { - List list = new ArrayList(fPositionUpdaters); - Iterator e = list.iterator(); - while (e.hasNext()) { - IPositionUpdater u = (IPositionUpdater) e.next(); - u.update(event); - } - } - - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IExecutionDelegatable.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IExecutionDelegatable.java deleted file mode 100644 index 03ed2675ef..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IExecutionDelegatable.java +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import org.eclipse.wst.sse.core.internal.IExecutionDelegate; - -public interface IExecutionDelegatable { - - void setExecutionDelegate(IExecutionDelegate executionDelegate); -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IRegionComparible.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IRegionComparible.java deleted file mode 100644 index 3230439abb..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IRegionComparible.java +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2004 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -public interface IRegionComparible { - boolean regionMatches(int offset, int length, String stringToCompare); - - boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare); - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/JobSafeStructuredDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/JobSafeStructuredDocument.java deleted file mode 100644 index 502b5081b9..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/JobSafeStructuredDocument.java +++ /dev/null @@ -1,249 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2009 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import java.util.Stack; - -import org.eclipse.core.runtime.ISafeRunnable; -import org.eclipse.core.runtime.jobs.ILock; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.DocumentRewriteSession; -import org.eclipse.jface.text.DocumentRewriteSessionType; -import org.eclipse.wst.sse.core.internal.IExecutionDelegate; -import org.eclipse.wst.sse.core.internal.ILockable; -import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser; -import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent; - -/** - * An IStructuredDocument that performs most of its computation and event - * notification through an IExecutionDelegate. - * - * If the delegate has not been set, we execute on current thread, like - * "normal". This is the case for normal non-editor use (which should still, - * ultimately, be protected by a scheduling rule). For every operation, a - * runnable is created, even if later (in the execution delegate instance) it - * is decided nothing special is needed (that is, in fact being called from an - * editor's display thread, in which case its just executed) in the UI. - */ -public class JobSafeStructuredDocument extends BasicStructuredDocument implements IExecutionDelegatable, ILockable { - - private static abstract class JobSafeRunnable implements ISafeRunnable { - public void handleException(Throwable exception) { - // logged in SafeRunner - } - } - - private Stack fExecutionDelegates = new Stack(); - private ILock fLockable = Job.getJobManager().newLock(); - - public JobSafeStructuredDocument() { - super(); - } - - - public JobSafeStructuredDocument(RegionParser parser) { - super(parser); - } - - - /** - * - */ - protected final void acquireLock() { - getLockObject().acquire(); - } - - private IExecutionDelegate getExecutionDelegate() { - if (!fExecutionDelegates.isEmpty()) - return (IExecutionDelegate) fExecutionDelegates.peek(); - return null; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.ILockable#getLock() - */ - - public ILock getLockObject() { - return fLockable; - } - - - /** - * - */ - protected final void releaseLock() { - getLockObject().release(); - } - - /* - * @see org.eclipse.jface.text.IDocument.replace(int, int, String) - */ - public void replace(final int offset, final int length, final String text) throws BadLocationException { - IExecutionDelegate delegate = getExecutionDelegate(); - if (delegate == null) { - super.replace(offset, length, text); - } - else { - JobSafeRunnable runnable = new JobSafeRunnable() { - public void run() throws Exception { - JobSafeStructuredDocument.super.replace(offset, length, text); - } - }; - delegate.execute(runnable); - } - } - - /* - * @see org.eclipse.jface.text.IDocumentExtension4.replace(int, int, String, long) - */ - public void replace(final int offset, final int length, final String text, final long modificationStamp) throws BadLocationException { - IExecutionDelegate delegate = getExecutionDelegate(); - if (delegate == null) { - super.replace(offset, length, text, modificationStamp); - } - else { - JobSafeRunnable runnable = new JobSafeRunnable() { - public void run() throws Exception { - JobSafeStructuredDocument.super.replace(offset, length, text, modificationStamp); - } - }; - delegate.execute(runnable); - } - } - - /* (non-Javadoc) - * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#replaceText(java.lang.Object, int, int, java.lang.String) - */ - public StructuredDocumentEvent replaceText(final Object requester, final int start, final int replacementLength, final String changes) { - StructuredDocumentEvent event = null; - IExecutionDelegate delegate = getExecutionDelegate(); - if (delegate == null) { - event = super.replaceText(requester, start, replacementLength, changes); - } - else { - final Object[] resultSlot = new Object[1]; - JobSafeRunnable runnable = new JobSafeRunnable() { - public void run() throws Exception { - resultSlot[0] = JobSafeStructuredDocument.super.replaceText(requester, start, replacementLength, changes); - } - }; - delegate.execute(runnable); - event = (StructuredDocumentEvent) resultSlot[0]; - } - return event; - } - - /* (non-Javadoc) - * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#replaceText(java.lang.Object, int, int, java.lang.String, boolean) - */ - public StructuredDocumentEvent replaceText(final Object requester, final int start, final int replacementLength, final String changes, final boolean ignoreReadOnlySettings) { - StructuredDocumentEvent event = null; - IExecutionDelegate delegate = getExecutionDelegate(); - if (delegate == null) { - event = super.replaceText(requester, start, replacementLength, changes, ignoreReadOnlySettings); - } - else { - final Object[] resultSlot = new Object[1]; - JobSafeRunnable runnable = new JobSafeRunnable() { - public void run() throws Exception { - resultSlot[0] = JobSafeStructuredDocument.super.replaceText(requester, start, replacementLength, changes, ignoreReadOnlySettings); - } - - public void handleException(Throwable exception) { - resultSlot[0] = new NoChangeEvent(JobSafeStructuredDocument.this, requester, changes, start, replacementLength); - super.handleException(exception); - } - }; - delegate.execute(runnable); - event = (StructuredDocumentEvent) resultSlot[0]; - } - return event; - } - - public void setExecutionDelegate(IExecutionDelegate delegate) { - if (delegate != null) - fExecutionDelegates.push(delegate); - else if (!fExecutionDelegates.isEmpty()) - fExecutionDelegates.pop(); - } - - public StructuredDocumentEvent setText(final Object requester, final String theString) { - StructuredDocumentEvent event = null; - IExecutionDelegate executionDelegate = getExecutionDelegate(); - if (executionDelegate == null) { - event = super.setText(requester, theString); - } - else { - final Object[] resultSlot = new Object[1]; - JobSafeRunnable runnable = new JobSafeRunnable() { - public void run() throws Exception { - resultSlot[0] = JobSafeStructuredDocument.super.setText(requester, theString); - } - public void handleException(Throwable exception) { - resultSlot[0] = new NoChangeEvent(JobSafeStructuredDocument.this, requester, theString, 0, 0); - super.handleException(exception); - } - }; - executionDelegate.execute(runnable); - event = (StructuredDocumentEvent) resultSlot[0]; - } - return event; - } - - public DocumentRewriteSession startRewriteSession(DocumentRewriteSessionType sessionType) throws IllegalStateException { - DocumentRewriteSession session = null; - IExecutionDelegate executionDelegate = getExecutionDelegate(); - if (executionDelegate == null) { - session = internalStartRewriteSession(sessionType); - } - else { - final Object[] resultSlot = new Object[1]; - final DocumentRewriteSessionType finalSessionType = sessionType; - JobSafeRunnable runnable = new JobSafeRunnable() { - public void run() throws Exception { - resultSlot[0] = internalStartRewriteSession(finalSessionType); - } - }; - executionDelegate.execute(runnable); - if (resultSlot[0] instanceof Throwable) { - throw new RuntimeException((Throwable) resultSlot[0]); - } - else { - session = (DocumentRewriteSession) resultSlot[0]; - } - } - return session; - } - - public void stopRewriteSession(DocumentRewriteSession session) { - IExecutionDelegate executionDelegate = getExecutionDelegate(); - if (executionDelegate == null) { - internalStopRewriteSession(session); - } - else { - final DocumentRewriteSession finalSession = session; - JobSafeRunnable runnable = new JobSafeRunnable() { - public void run() throws Exception { - internalStopRewriteSession(finalSession); - } - }; - executionDelegate.execute(runnable); - } - } - - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/MinimalDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/MinimalDocument.java deleted file mode 100644 index de3ff23f39..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/MinimalDocument.java +++ /dev/null @@ -1,445 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.BadPositionCategoryException; -import org.eclipse.jface.text.IDocumentListener; -import org.eclipse.jface.text.IDocumentPartitioner; -import org.eclipse.jface.text.IDocumentPartitioningListener; -import org.eclipse.jface.text.IPositionUpdater; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.ITypedRegion; -import org.eclipse.jface.text.Position; -import org.eclipse.jface.text.TypedRegion; -import org.eclipse.wst.sse.core.internal.Logger; -import org.eclipse.wst.sse.core.internal.NotImplementedException; -import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento; -import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser; -import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener; -import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser; -import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager; - - -/** - * Purely a dummy "marker" instance for StructuredDocumentRegions which are - * created temorarily in the course of re-parsing. Primarily a place holder, - * but can be needed to get text from. - */ -public class MinimalDocument implements IStructuredDocument { - private SubSetTextStore data; - - /** - * Marked private to be sure never created without data being initialized. - * - */ - private MinimalDocument() { - super(); - } - - public MinimalDocument(SubSetTextStore initialContents) { - this(); - data = initialContents; - } - - public void addDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addDocumentChangedListener(IStructuredDocumentListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addDocumentChangingListener(IStructuredDocumentListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addDocumentListener(IDocumentListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addPosition(Position position) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addPositionCategory(String category) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addPositionUpdater(IPositionUpdater updater) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void addPrenotifiedDocumentListener(IDocumentListener documentAdapter) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void clearReadOnly(int startOffset, int length) { - // TODO: this is called from notifier loop inappropriately - // throw new NotImplementedException("intentionally not implemented"); - } - - public int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int computeNumberOfLines(String text) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public boolean containsPosition(String category, int offset, int length) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public boolean containsPositionCategory(String category) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public boolean containsReadOnly(int startOffset, int length) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void fireNewDocument(Object requester) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public String get() { - String result = null; - result = data.get(0, data.getLength()); - return result; - } - - public String get(int offset, int length) throws BadLocationException { - String result = null; - try { - result = data.get(offset, length); - } catch (StringIndexOutOfBoundsException e) { - throw new BadLocationException("offset: " + offset + " length: " + length + "\ndocument length: " + data.getLength()); - } - return result; - } - - public Object getAdapter(Class adapter) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public char getChar(int offset) throws BadLocationException { - return data.get(offset); - } - - public String getContentType(int offset) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IDocumentPartitioner getDocumentPartitioner() { - // temp fix - return null; - // throw new NotImplementedException("intentionally not implemented"); - } - - public EncodingMemento getEncodingMemento() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IStructuredDocumentRegion getFirstStructuredDocumentRegion() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IStructuredDocumentRegion getLastStructuredDocumentRegion() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public String[] getLegalContentTypes() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public String[] getLegalLineDelimiters() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int getLength() { - return data.getLength(); - } - - public String getPreferedLineDelimiter() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public String getLineDelimiter(int line) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IRegion getLineInformation(int line) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IRegion getLineInformationOfOffset(int offset) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int getLineLength(int line) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int getLineOffset(int line) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int getLineOfOffset(int offset) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int getNumberOfLines() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int getNumberOfLines(int offset, int length) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public RegionParser getParser() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public ITypedRegion getPartition(int offset) throws BadLocationException { - Logger.log(Logger.WARNING, "An instance of MinimalDocument was asked for its partition, sometime indicating a deleted region was being accessed."); //$NON-NLS-1$ - return new TypedRegion(0,0, "undefined"); //$NON-NLS-1$ - //throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public String[] getPositionCategories() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public Position[] getPositions(String category) throws BadPositionCategoryException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IPositionUpdater[] getPositionUpdaters() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IStructuredDocumentRegion getRegionAtCharacterOffset(int offset) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IStructuredDocumentRegionList getRegionList() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IStructuredTextReParser getReParser() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public String getText() { - return data.get(0, data.getLength()); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.text.IStructuredDocument#getUndoManager() - */ - public IStructuredTextUndoManager getUndoManager() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void insertPositionUpdater(IPositionUpdater updater, int index) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void makeReadOnly(int startOffset, int length) { - // TODO: this is called from notifier loop inappropriately - // throw new NotImplementedException("intentionally not implemented"); - } - - public IStructuredDocument newInstance() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#registerPostNotificationReplace(org.eclipse.jface.text.IDocumentListener, - * org.eclipse.jface.text.IDocumentExtension.IReplace) - */ - public void registerPostNotificationReplace(IDocumentListener owner, IReplace replace) throws UnsupportedOperationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removeDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removeDocumentChangedListener(IStructuredDocumentListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removeDocumentChangingListener(IStructuredDocumentListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removeDocumentListener(IDocumentListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removePosition(Position position) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removePosition(String category, Position position) throws BadPositionCategoryException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removePositionCategory(String category) throws BadPositionCategoryException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removePositionUpdater(IPositionUpdater updater) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void removePrenotifiedDocumentListener(IDocumentListener documentAdapter) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void replace(int offset, int length, String text) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - // data.replace(offset, length, text); - } - - public StructuredDocumentEvent replaceText(Object source, int oldStart, int replacementLength, String requestedChange) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.text.IStructuredDocument#replaceText(java.lang.Object, - * int, int, java.lang.String, boolean) - */ - public StructuredDocumentEvent replaceText(Object source, int oldStart, int replacementLength, String requestedChange, boolean ignoreReadOnlySetting) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#resumePostNotificationProcessing() - */ - public void resumePostNotificationProcessing() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public int search(int startOffset, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void set(String text) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - // data.set(text); - } - - public void setDocumentPartitioner(IDocumentPartitioner partitioner) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void setEncodingMemento(EncodingMemento encodingMemento) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public void setPreferredLineDelimiter(String delimiter) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public StructuredDocumentEvent setText(Object requester, String allText) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.wst.sse.core.text.IStructuredDocument#setUndoManager(org.eclipse.wst.sse.core.undo.StructuredTextUndoManager) - */ - public void setUndoManager(IStructuredTextUndoManager undoManager) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#startSequentialRewrite(boolean) - */ - public void startSequentialRewrite(boolean normalize) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#stopPostNotificationProcessing() - */ - public void stopPostNotificationProcessing() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.IDocumentExtension#stopSequentialRewrite() - */ - public void stopSequentialRewrite() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public String getLineDelimiter() { - return null; - } - - public String getPreferredLineDelimiter() { - return null; - } - - public void setLineDelimiter(String delimiter) { - - } - - public IStructuredDocumentRegion[] getStructuredDocumentRegions() { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } - - public IStructuredDocumentRegion[] getStructuredDocumentRegions(int start, int length) { - throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$ - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/ReadOnlyPosition.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/ReadOnlyPosition.java deleted file mode 100644 index 4c4bccfeb1..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/ReadOnlyPosition.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006 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.wst.sse.core.internal.text; - -import org.eclipse.jface.text.Position; - -class ReadOnlyPosition extends Position { - private boolean fIncludeStartOffset = false; - - public ReadOnlyPosition(int newOffset, int newLength, boolean includeStart) { - super(newOffset, newLength); - fIncludeStartOffset = includeStart; - } - - public boolean overlapsWith(int newOffset, int newLength) { - boolean overlapsWith = super.overlapsWith(newOffset, newLength); - if (overlapsWith) { - /* - * BUG157526 If at the start of the read only region and length = - * 0 most likely asking to insert and want to all inserting before - * read only region - */ - if (fIncludeStartOffset && (newLength == 0) && (this.length != 0) && (newOffset == this.offset)) { - overlapsWith = false; - } - } - return overlapsWith; - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentReParser.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentReParser.java deleted file mode 100644 index f846682f8a..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentReParser.java +++ /dev/null @@ -1,1658 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2010 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * David Carver (Intalio) - bug 300427 - Comparison of String Objects using == or != - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import java.util.Iterator; -import java.util.List; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.FindReplaceDocumentAdapter; -import org.eclipse.jface.text.IRegion; -import org.eclipse.wst.sse.core.internal.Logger; -import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTagParser; -import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; -import org.eclipse.wst.sse.core.internal.util.Debug; -import org.eclipse.wst.sse.core.internal.util.Utilities; -import org.eclipse.wst.sse.core.utils.StringUtils; - - -/** - * This class provides a centralized place to put "reparsing" logic. This is - * the logic that reparses the text incrementally, as a user types in new - * characters, or DOM nodes are inserted or deleted. Note: it is not a thread - * safe class. - */ -public class StructuredDocumentReParser implements IStructuredTextReParser { - protected IStructuredDocumentRegion dirtyEnd = null; - protected IStructuredDocumentRegion dirtyStart = null; - final private String doubleQuote = new String(new char[]{'\"'}); - protected final CoreNodeList EMPTY_LIST = new CoreNodeList(); - protected String fChanges; - protected String fDeletedText; - protected boolean fIsEntireDocument; - - private FindReplaceDocumentAdapter fFindReplaceDocumentAdapter = null; - protected int fLengthDifference; - protected int fLengthToReplace; - protected Object fRequester; - protected int fStart; - // note: this is the impl class of IStructuredDocument, not the interface - // FUTURE_TO_DO: I believe some of these can be made private now.? - protected BasicStructuredDocument fStructuredDocument; - - /** - * variable used in anticiapation of multithreading - */ - protected boolean isParsing; - final private String singleQuote = new String(new char[]{'\''}); - - public StructuredDocumentReParser() { - super(); - } - - public StructuredDocumentEvent _checkBlockNodeList(List blockTagList) { - StructuredDocumentEvent result = null; - if (blockTagList != null) { - for (int i = 0; i < blockTagList.size(); i++) { - org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker blockTag = (org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker) blockTagList.get(i); - String tagName = blockTag.getTagName(); - result = checkForCriticalName("<" + tagName); //$NON-NLS-1$ - if (result != null) - break; - result = checkForCriticalName("</" + tagName); //$NON-NLS-1$ - if (result != null) - break; - } - } - return result; - } - - /** - * Common utility for checking for critical word such as " <SCRIPT>" - */ - private StructuredDocumentEvent _checkForCriticalWord(String criticalTarget, boolean checkEnd) { - StructuredDocumentEvent result = null; - int documentLength = fStructuredDocument.getLength(); - int propLen = fLengthToReplace; - if (propLen > documentLength) - propLen = documentLength; - int startNeighborhood = fStart - criticalTarget.length(); - int adjustInsert = 0; - if (startNeighborhood < 0) { - adjustInsert = 0 - startNeighborhood; - startNeighborhood = 0; - } - int endNeighborhood = fStart + fLengthToReplace + criticalTarget.length() - 1; - if (endNeighborhood > documentLength) - endNeighborhood = documentLength - 1; - int oldlen = endNeighborhood - startNeighborhood; // + 1; - if (oldlen + startNeighborhood > documentLength) { - oldlen = documentLength - startNeighborhood; - } - String oldText = fStructuredDocument.get(startNeighborhood, oldlen); - String peek = StringUtils.paste(oldText, fChanges, criticalTarget.length() - adjustInsert, fLengthToReplace); - boolean isCriticalString = checkTagNames(oldText, criticalTarget, checkEnd); - boolean toBeCriticalString = checkTagNames(peek, criticalTarget, checkEnd); - if ((isCriticalString != toBeCriticalString) || // OR if both are - // critical and there's - // a change in the end - // tag ('>') - ((isCriticalString && toBeCriticalString) && (changeInIsEndedState(oldText, peek)))) { - // if it involves a change of a critical string (making one where - // there wasn't, or removing - // one where there was one) then reparse everthing. - result = reparse(0, documentLength - 1); - } - return result; - } - - private int _computeStartOfDifferences(CoreNodeList oldNodes, CoreNodeList newNodes) { - int startOfDifferences = -1; - int newNodesLength = newNodes.getLength(); - boolean foundDifference = false; - boolean done = false; - // we'll control our loop based on the old List length - int oldNodesLength = oldNodes.getLength(); - // be sure to check 'done' first, so startOfDifferences isn't - // icremented if done is true - done : while ((!done) && (++startOfDifferences < oldNodesLength)) { - IStructuredDocumentRegion oldNode = oldNodes.item(startOfDifferences); - // this lessThanEffectedRegion is to check to be sure the node is - // infact a candidate - // to be considered as "old". This check is important for the case - // where some - // text is replaceing text that - // appears identical, but is a different instance. For example, if - // the text - // is <P><B></B></P> and <B></B> is inserted at postion 3, - // resulting in <P><B></B><B></B></P> - // we do not want the - // first <B> to be considered old ... it is the new one, the - // second - // <B> is the old one. - if (_lessThanEffectedRegion(oldNode)) { - // be sure to check that we have new nodes to compare against. - if (startOfDifferences > newNodesLength) { - foundDifference = false; - done = true; - continue done; - } else { - // - IStructuredDocumentRegion newNode = newNodes.item(startOfDifferences); - // note: shift is 0 while at beginning of list, before the - // insertion (or deletion) point. After that, it is - // fStart+fLengthDifference - if (!(oldNode.sameAs(newNode, 0))) { - foundDifference = true; - done = true; - continue done; - } else { // if they are equal, then we will be keeping the - // old one, so - // we need to be sure its parentDocument is set back - // to - // the right instance - oldNode.setParentDocument(fStructuredDocument); - } - } - } else { - // we didn't literally find a difference, but we count it as - // such by implication - foundDifference = true; - done = true; - continue done; - } - } - // if we literally found a difference, then all is ok and we can - // return - // it. - // if we did not literally find one, then we have to decide why. - if (!foundDifference) { - if (newNodesLength == oldNodesLength) { // then lists are - // identical - // (and may be of zero - // length) - startOfDifferences = -1; - } else { - if (newNodesLength > oldNodesLength) { // then lists are - // identical except for - // newNodes added - startOfDifferences = oldNodesLength; - } else { - if (newNodesLength < oldNodesLength) { // then lists are - // identical except - // for old Nodes - // deleted - startOfDifferences = newNodesLength; - } - } - } - } - return startOfDifferences; - } - - private int _computeStartOfDifferences(IStructuredDocumentRegion oldNodeParam, ITextRegionList oldRegions, IStructuredDocumentRegion newNodeParam, ITextRegionList newRegions) { - int startOfDifferences = -1; - int newRegionsLength = newRegions.size(); - boolean foundDifference = false; - boolean done = false; - // we'll control our loop based on the old List length - int oldRegionsLength = oldRegions.size(); - // be sure to check 'done' first, so startOfDifferences isn't - // icremented if done is true - done : while ((!done) && (++startOfDifferences < oldRegionsLength)) { - ITextRegion oldRegion = oldRegions.get(startOfDifferences); - // this lessThanEffectedRegion is to check to be sure the node is - // infact a candidate - // to be considered as "old". This check is important for the case - // where some - // text is replaceing text that - // appears identical, but is a different instance. For example, if - // the text - // is <P><B></B></P> and <B></B> is inserted at postion 3, - // resulting in <P><B></B><B></B></P> - // we do not want the - // first <B> to be considered old ... it is the new one, the - // second - // <B> is the old one. - if (_lessThanEffectedRegion(oldNodeParam, oldRegion)) { - // be sure to check that we have new nodes to compare against. - if (startOfDifferences > newRegionsLength) { - foundDifference = false; - done = true; - continue done; - } else { - // - ITextRegion newRegion = newRegions.get(startOfDifferences); - // note: shift is 0 while at beginning of list, before the - // insertion (or deletion) point. After that, it is - // fStart+fLengthDifference - if (!(oldNodeParam.sameAs(oldRegion, newNodeParam, newRegion, 0))) { - foundDifference = true; - done = true; - continue done; - } else { - // if they are equal, then we will be keeping the old - // one. - // unlike the flatnode case, there is no reason to - // update - // the textstore, since its the same text store in - // either case - // (since its the same flatnode) - //oldRegion.setTextStore(fStructuredDocument.parentDocument); - } - } - } else { - // we didn't literally find a difference, but we count it as - // such by implication - foundDifference = true; - done = true; - continue done; - } - } - // if we literally found a difference, then all is ok and we can - // return - // it. - // if we did not literally find one, then we have to decide why. - if (!foundDifference) { - if (newRegionsLength == oldRegionsLength) { // then lists are - // identical (and may - // be of zero length) - startOfDifferences = -1; - } else { - if (newRegionsLength > oldRegionsLength) { // then lists are - // identical except - // for newRegions - // added - startOfDifferences = oldRegionsLength; - } else { - if (newRegionsLength < oldRegionsLength) { // then lists - // are identical - // except for - // old Nodes - // deleted - startOfDifferences = newRegionsLength; - } - } - } - } - return startOfDifferences; - } - - /** - * Part 1 of 2 steps to do a core_reparse - * - * Parses a portion of the current text in the IStructuredDocument and - * returns the raw result - */ - private IStructuredDocumentRegion _core_reparse_text(int rescanStart, int rescanEnd) { - fStructuredDocument.resetParser(rescanStart, rescanEnd); - return fStructuredDocument.getParser().getDocumentRegions(); - } - - /** - * Part 2 of 2 steps to do a core_reparse - * - * Integrates a list of StructuredDocumentRegions based on the current - * text contents of the IStructuredDocument into the IStructuredDocument - * data structure - */ - private StructuredDocumentEvent _core_reparse_update_model(IStructuredDocumentRegion newNodesHead, int rescanStart, int rescanEnd, CoreNodeList oldNodes, boolean firstTime) { - StructuredDocumentEvent result = null; - CoreNodeList newNodes = null; - // rescan - newNodes = new CoreNodeList(newNodesHead); - // adjust our newNode chain so the offset positions match - // our text store (not the simple string of text reparsed) - StructuredDocumentRegionIterator.adjustStart(newNodesHead, rescanStart); - // initialize the parentDocument variable of each instance in the new - // chain - StructuredDocumentRegionIterator.setParentDocument(newNodesHead, fStructuredDocument); - // initialize the structuredDocument variable of each instance in the - // new chain - //StructuredDocumentRegionIterator.setStructuredDocument(newNodesHead, - // fStructuredDocument); - // - if (firstTime) { - fStructuredDocument.setCachedDocumentRegion(newNodesHead); - fStructuredDocument.initializeFirstAndLastDocumentRegion(); - // note: since we are inserting nodes, for the first time, there - // is - // no adjustments - // to downstream stuff necessary. - result = new StructuredDocumentRegionsReplacedEvent(fStructuredDocument, fRequester, oldNodes, newNodes, fChanges, fStart, fLengthToReplace, fIsEntireDocument); - } else { - // note: integrates changes into model as a side effect - result = minimumEvent(oldNodes, newNodes); - } - result.setDeletedText(fDeletedText); - return result; - } - - private CoreNodeList _formMinimumList(CoreNodeList flatnodes, int startOfDifferences, int endOfDifferences) { - CoreNodeList minimalNodes = null; - // if startOfDifferces is still its initial value, then we have an - // empty document - if (startOfDifferences == -1) { - minimalNodes = EMPTY_LIST; - } else { - // if we do not have any flatnode in our flatnode list, then - // simply - // return our standard empty list - if (flatnodes.getLength() == 0) { - minimalNodes = EMPTY_LIST; - } else { - // if startOfDifferences is greater than endOfDifferences, - // then - // that means the calculations "crossed" each other, and - // hence, - // there really is no differences, so, again, return the empty - // list - if (startOfDifferences > endOfDifferences) { - minimalNodes = EMPTY_LIST; - } else { - // the last check be sure we have some differnces - if ((endOfDifferences > -1)) { - minimalNodes = new CoreNodeList(flatnodes.item(startOfDifferences), flatnodes.item(endOfDifferences)); - } else { - // there were no differences, the list wasn't - // minimized, so simply return it. - minimalNodes = flatnodes; - } - } - } - } - return minimalNodes; - } - - private boolean _greaterThanEffectedRegion(IStructuredDocumentRegion oldNode) { - boolean result = false; - int nodeStart = oldNode.getStartOffset(); - int changedRegionEnd = fStart + fLengthToReplace - 1; - result = nodeStart > changedRegionEnd; - return result; - } - - private boolean _greaterThanEffectedRegion(IStructuredDocumentRegion oldNode, ITextRegion oldRegion) { - boolean result = false; - int regionStartOffset = oldNode.getStartOffset(oldRegion); - int effectedRegionEnd = fStart + fLengthToReplace - 1; - result = regionStartOffset > effectedRegionEnd; - return result; - } - - private boolean _lessThanEffectedRegion(IStructuredDocumentRegion oldNode) { - boolean result = false; - int nodeEnd = oldNode.getEndOffset() - 1; - result = nodeEnd < fStart; - return result; - } - - private boolean _lessThanEffectedRegion(IStructuredDocumentRegion oldNode, ITextRegion oldRegion) { - boolean result = false; - int nodeEnd = oldNode.getEndOffset(oldRegion) - 1; - result = nodeEnd < fStart; - return result; - } - - private boolean _regionsSameKind(ITextRegion newRegion, ITextRegion oldRegion) { - boolean result = false; - // if one region is a container region, and the other not, always - // return false - // else, just check their type. - // DW druing refactoring, looks like a "typo" here, using 'old' in - // both. - // if (isContainerRegion(oldRegion) != isContainerRegion(oldRegion)) - if (isCollectionRegion(oldRegion) != isCollectionRegion(newRegion)) - result = false; - else if (oldRegion.getType().equals(newRegion.getType())) - result = true; - return result; - } - - // private boolean hasCollectionRegions(ITextRegion aRegion) { - // boolean result = false; - // if (aRegion instanceof ITextRegionCollection) { - // ITextRegionCollection regionContainter = (ITextRegionCollection) - // aRegion; - // ITextRegionList regions = regionContainter.getRegions(); - // Iterator iterator = regions.iterator(); - // while (iterator.hasNext()) { - // if (aRegion instanceof ITextRegionCollection) { - // result = true; - // break; - // } - // } - // } - // return result; - // } - /** - * This method is specifically to detect changes in 'isEnded' state, - * although it still does so with heuristics. If number of '>' changes, - * assume the isEnded state has changed. - */ - private boolean changeInIsEndedState(String oldText, String newText) { - int nOld = StringUtils.occurrencesOf(oldText, '>'); - int nNew = StringUtils.occurrencesOf(newText, '>'); - return !(nOld == nNew); - } - - private void checkAndAssignParent(IStructuredDocumentRegion oldNode, ITextRegion region) { - if (region instanceof ITextRegionContainer) { - ((ITextRegionContainer) region).setParent(oldNode); - return; - } - if (region instanceof ITextRegionCollection) { - ITextRegionCollection textRegionCollection = (ITextRegionCollection) region; - ITextRegionList regionList = textRegionCollection.getRegions(); - for (int i = 0; i < regionList.size(); i++) { - ITextRegion innerRegion = regionList.get(i); - checkAndAssignParent(oldNode, innerRegion); - } - } - } - - /** - * A change to a CDATA tag can result in all being reparsed. - */ - private StructuredDocumentEvent checkForCDATA() { - StructuredDocumentEvent result = null; - result = checkForCriticalKey("<![CDATA["); //$NON-NLS-1$ - if (result == null) - result = checkForCriticalKey("]]>"); //$NON-NLS-1$ - return result; - } - - /** - * If a comment start or end tag is being added or deleted, we'll rescan - * the whole document. The reason is that content that is revealed or - * commented out can effect the interpretation of the rest of the - * document. Note: for now this is very XML specific, can refactor/improve - * later. - */ - protected StructuredDocumentEvent checkForComments() { - StructuredDocumentEvent result = null; - result = checkForCriticalKey("<!--"); //$NON-NLS-1$ - if (result == null) - result = checkForCriticalKey("-->"); //$NON-NLS-1$ - // we'll also check for these degenerate cases - if (result == null) - result = checkForCriticalKey("<!--->"); //$NON-NLS-1$ - return result; - } - - /** - * Common utility for checking for critical word such as " <SCRIPT>" - */ - protected StructuredDocumentEvent checkForCriticalKey(String criticalTarget) { - return _checkForCriticalWord(criticalTarget, false); - } - - /** - * Common utility for checking for critical word such as " <SCRIPT>" - */ - private StructuredDocumentEvent checkForCriticalName(String criticalTarget) { - return _checkForCriticalWord(criticalTarget, true); - } - - // /** - // * Currently this method is pretty specific to ?ML - // * @deprecated - not really deprecated, but plan to make - // * protected ... I'm not sure why its public or misspelled? - // */ - protected StructuredDocumentEvent checkForCrossStructuredDocumentRegionBoundryCases() { - StructuredDocumentEvent result = null; - // Case 1: See if the language's syntax requires that multiple - // StructuredDocumentRegions be rescanned - if (result == null) { - result = checkForCrossStructuredDocumentRegionSyntax(); - } - // Case 2: "block tags" whose content is left unparsed - if (result == null) { - Object parser = fStructuredDocument.getParser(); - if (parser instanceof BlockTagParser) { - List blockTags = ((BlockTagParser) parser).getBlockMarkers(); - result = _checkBlockNodeList(blockTags); - } - } - // FUTURE_TO_DO: is there a better place to do this? - // or! do we already do it some other more central place? - if (result != null) { - result.setDeletedText(fDeletedText); - } - return result; - } - - /** - * Allow a reparser to check for extra syntactic cases that require - * parsing beyond the flatNode boundary. - * - * This implementation is very XML-centric. - */ - protected StructuredDocumentEvent checkForCrossStructuredDocumentRegionSyntax() { - StructuredDocumentEvent result; - // Case 1: Quote characters are involved - result = checkForQuotes(); - if (result == null) { - // Case 2: The input forms or undoes a comment beginning or - // comment - // end - result = checkForComments(); - } - if (result == null) { - // Case 3: The input forms or undoes a processing instruction - result = checkForPI(); - } - if (result == null) { - // Case 4: The input forms or undoes a CDATA section - result = checkForCDATA(); - } - return result; - } - - /** - * Checks to see if change request exactly matches the text it would be - * replacing. (In future, this, or similar method is where to check for - * "read only" attempted change.) - */ - private StructuredDocumentEvent checkForNoChange() { - StructuredDocumentEvent result = null; - // don't check equals unless lengths match - // should be a tiny bit faster, since usually not - // of equal lengths (I'm surprised String's equals method - // doesn't do this.) - if ((fChanges != null) && (fDeletedText != null) && (fChanges.length() == fDeletedText.length()) && (fChanges.equals(fDeletedText))) { - result = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace); - ((NoChangeEvent)result).reason = NoChangeEvent.NO_CONTENT_CHANGE; - } - return result; - } - - /** - * A change to a PI tag can result in all being reparsed. - */ - private StructuredDocumentEvent checkForPI() { - StructuredDocumentEvent result = null; - result = checkForCriticalKey("<?"); //$NON-NLS-1$ - if (result == null) - result = checkForCriticalKey("?>"); //$NON-NLS-1$ - return result; - } - - // For simplicity, if either text to be deleted, or text to be inserted - // contains at least - // one quote, we'll search for previous quote in document, if any, and use - // that flatnode as - // a dirty start, and we'll use end of document as dirty end. We need to - // assume either \" or - // \' is an exceptable quote. (NOTE: this is, loosely, an XML assumption - // -- - // other languages - // would differ, but we'll "hard code" for XML for now. - // future_TODO: this is a really bad heuristic ... we should be looking - // for - // odd number of quotes - // within a structuredDocumentRegion (or something!) This causes way too - // much reparsing on - // simple cases, like deleting a tag with a quoted attribute! - private StructuredDocumentEvent checkForQuotes() { - // routine is supported with null or empty string meaning the same - // thing: deletion - if (fChanges == null) - fChanges = ""; //$NON-NLS-1$ - // - StructuredDocumentEvent result = null; - try { - int dirtyStartPos = -1; - String proposedDeletion = fStructuredDocument.get(fStart, fLengthToReplace); - if (fStart < fStructuredDocument.getLength()) { - if ((fChanges.indexOf(singleQuote) > -1) || (proposedDeletion.indexOf(singleQuote) > -1)) { - IRegion singleQuoteRegion = getFindReplaceDocumentAdapter().find(fStart, singleQuote, false, false, false, false); - if (singleQuoteRegion != null) { - dirtyStartPos = singleQuoteRegion.getOffset(); - } - } else if ((fChanges.indexOf(doubleQuote) > -1) || (proposedDeletion.indexOf(doubleQuote) > -1)) { - IRegion doubleQuoteRegion = getFindReplaceDocumentAdapter().find(fStart, doubleQuote, false, false, false, false); - if (doubleQuoteRegion != null) { - dirtyStartPos = doubleQuoteRegion.getOffset(); - } - } - } - if (dirtyStartPos > -1) { - // then we found one, do create new structuredDocument event - // based on the previous quote to end of document - // except, we need to be positive that the previous quote is - // in a "safe start" region (e.g. if in JSP content, we need - // to - // backup till we include the whole JSP region, in order for - // it - // to be correctly re-parsed. The backing up is done in the - // reparse/find dirty start from hint - // method. - result = reparse(dirtyStartPos, fStructuredDocument.getLength() - 1); - } - } catch (BadLocationException e) { - Logger.logException(e); - } - if (result != null) { - result.setDeletedText(fDeletedText); - } - return result; - } - - private StructuredDocumentEvent checkHeuristics() { - StructuredDocumentEvent result = null; - result = checkForNoChange(); - if (result == null) { - result = checkForCrossStructuredDocumentRegionBoundryCases(); - if (result == null) { - result = quickCheck(); - } - } - return result; - } - - /** - * Takes into account "tag name" rules for comparisons; case-insensitive. - */ - private boolean checkTagNames(String compareText, String criticalTarget, boolean checkEnd) { - boolean result = false; - if ((compareText == null) || (criticalTarget == null)) - return false; - int posOfCriticalWord = compareText.toLowerCase().indexOf(criticalTarget.toLowerCase()); - result = posOfCriticalWord > -1; - if (checkEnd && result) { - // instead of returning true right away, we'll only return true - // the - // potentially matched tag is indeed a tag, for example, if - // <SCRIPT - // becomes <SCRIPTS we don't want to say the latter is a critical - // tag - int lastPos = posOfCriticalWord + criticalTarget.length(); - if (lastPos < compareText.length()) { - char lastChar = compareText.charAt(lastPos); - // Future: check formal definition of this java method, vs. - // XML - // parsing rules - result = (!Character.isLetterOrDigit(lastChar)); - } - } - return result; - } - - /** - * The core reparsing method ... after the dirty start and dirty end have - * been calculated elsewhere, and the text updated. - */ - protected StructuredDocumentEvent core_reparse(int rescanStart, int rescanEnd, CoreNodeList oldNodes, boolean firstTime) { - IStructuredDocumentRegion newNodesHead = null; - StructuredDocumentEvent result = null; - newNodesHead = _core_reparse_text(rescanStart, rescanEnd); - result = _core_reparse_update_model(newNodesHead, rescanStart, rescanEnd, oldNodes, firstTime); - return result; - } - - /** - * Resets state to "not parsing" - */ - private synchronized void endReParse() { - isParsing = false; - dirtyStart = null; - dirtyEnd = null; - fChanges = null; - fDeletedText = null; - fIsEntireDocument = false; - } - - protected IStructuredDocumentRegion findDirtyEnd(int end) { - // Caution: here's one place we have to cast - IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(end); - // if not well formed, get one past, if there is something there - if ((result != null) && (!result.isEnded())) { - if (result.getNext() != null) { - result = result.getNext(); - } - } - // also, get one past if exactly equal to the end (this was needed - // as a simple fix to when a whole exact region is deleted. - // there's probably a better way. - if ((result != null) && (end == result.getEnd())) { - if (result.getNext() != null) { - result = result.getNext(); - } - } - // moved to subclass for quick transition - // 12/6/2001 - Since we've changed the parser/scanner to allow a lone - // '<' without - // always interpretting it as start of a tag name, we need to be a - // little fancier, in order - // to "skip" over any plain 'ol content between the lone '<' and any - // potential meating - // regions past plain 'ol content. - // if (isLoneOpenFollowedByContent(result) && (result.getNext() != - // null)) { - // result = result.getNext(); - // } - if (result != null) - fStructuredDocument.setCachedDocumentRegion(result); - dirtyEnd = result; - return dirtyEnd; - } - - protected void findDirtyStart(int start) { - IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(start); - // heuristic: if the postion is exactly equal to the start, then - // go back one more, if it exists. This prevents problems with - // insertions - // of text that should be merged with the previous node instead of - // simply hung - // off of it as a separate node (ex.: XML content inserted right - // before - // an open - // bracket should become part of the previous content node) - if (result != null) { - IStructuredDocumentRegion previous = result.getPrevious(); - if ((previous != null) && ((!(previous.isEnded())) || (start == result.getStart()))) { - result = previous; - } - // If we are now at the end of a "tag dependent" content area (or - // JSP area) - // then we need to back up all the way to the beginning of that. - IStructuredDocumentRegion potential = result; - // moved to subclass to speed transition - // while (isPartOfBlockRegion(potential)) { - // potential = potential.getPrevious(); - // } - if (potential != null) { - result = potential; - fStructuredDocument.setCachedDocumentRegion(result); - } - } - dirtyStart = result; - } - - protected CoreNodeList formOldNodes(IStructuredDocumentRegion dirtyStart, IStructuredDocumentRegion dirtyEnd) { - CoreNodeList oldNodes = new CoreNodeList(dirtyStart, dirtyEnd); - // Now save the old text, that "goes with" the old nodes and regions. - // Notice we are getting it directly from the text store - String oldText = null; - int oldStart = -1; - int oldEnd = -1; - // make sure there is some text, if not, use empty string - // (if one node is not null, the other should ALWAYS be not null too, - // since it - // would at least be equal to it.) - if (dirtyStart != null) { - oldStart = dirtyStart.getStart(); - oldEnd = dirtyEnd.getEnd(); - oldText = fStructuredDocument.get(oldStart, oldEnd - oldStart); - } else { - oldStart = 0; - oldEnd = 0; - oldText = ""; //$NON-NLS-1$ - } - // create a temporary text store for this text - SubSetTextStore subTextStore = new SubSetTextStore(oldText, oldStart, oldEnd, fStructuredDocument.getLength()); - // Now update the text store of the oldNodes - StructuredDocumentRegionIterator.setParentDocument(oldNodes, new MinimalDocument(subTextStore)); - return oldNodes; - } - - /** - * @return Returns the findReplaceDocumentAdapter. - */ - public FindReplaceDocumentAdapter getFindReplaceDocumentAdapter() { - if (fFindReplaceDocumentAdapter == null) { - fFindReplaceDocumentAdapter = new FindReplaceDocumentAdapter(fStructuredDocument); - } - return fFindReplaceDocumentAdapter; - } - - // Note: if thead safety is needed, this and all the other public methods - // of this class - // should be synchronized. - public void initialize(Object requester, int start, int lengthToReplace, String changes) { - isParsing = true; - fRequester = requester; - fStart = start; - fLengthToReplace = lengthToReplace; - fChanges = changes; - // notice this one is derived - fLengthDifference = Utilities.calculateLengthDifference(fChanges, fLengthToReplace); - fDeletedText = fStructuredDocument.get(fStart, fLengthToReplace); - int docLength = fStructuredDocument.getLength(); - fIsEntireDocument = lengthToReplace >= docLength && docLength > 0; - } - - protected void insertNodes(IStructuredDocumentRegion previousOldNode, IStructuredDocumentRegion nextOldNode, CoreNodeList newNodes) { - // - IStructuredDocumentRegion firstNew = null; - IStructuredDocumentRegion lastNew = null; - // - IStructuredDocumentRegion oldPrevious = previousOldNode; - IStructuredDocumentRegion oldNext = nextOldNode; - // - if (newNodes.getLength() > 0) { - // get pointers - firstNew = newNodes.item(0); - lastNew = newNodes.item(newNodes.getLength() - 1); - // switch surrounding StructuredDocumentRegions' references to - // lists - if (oldPrevious != null) - oldPrevious.setNext(firstNew); - if (oldNext != null) { - oldNext.setPrevious(lastNew); - } else { - // SIDE EFFECT - // if oldNext is null, that means we are replaceing the - // lastNode in the chain, - // so we need to update the structuredDocuments lastNode as - // the - // last of the new nodes. - fStructuredDocument.setLastDocumentRegion(newNodes.item(newNodes.getLength() - 1)); - } - if (firstNew != null) - firstNew.setPrevious(oldPrevious); - if (lastNew != null) - lastNew.setNext(oldNext); - } - // else nothing to insert - } - - /** - * @param oldRegion - */ - private boolean isCollectionRegion(ITextRegion aRegion) { - return (aRegion instanceof ITextRegionCollection); - } - - /** - * @return boolean - */ - public boolean isParsing() { - return isParsing; - } - - /** - * The minimization algorithm simply checks the old nodes to see if any of - * them "survived" the rescan and are unchanged. If so, the instance of - * the old node is used instead of the new node. Before the requested - * change, need to check type, offsets, and text to determine if the same. - * After the requested change, need to check type and text, but adjust the - * offsets to what ever the change was. - */ - protected StructuredDocumentEvent minimumEvent(CoreNodeList oldNodes, CoreNodeList newNodes) { - StructuredDocumentEvent event = null; - CoreNodeList minimalOldNodes = null; - CoreNodeList minimalNewNodes = null; - // To minimize nodes, we'll collect all those - // that are not equal into old and new lists - // Note: we assume that old and new nodes - // are basically contiguous -- and we force it to be so, - // by starting at the beginning to - // find first difference, and then starting at the end to find - // last difference. Everything in between we assume is different. - // - // - // - // startOfDifferences is the index into the core node list where the - // first difference - // occurs. But it may point into the old or the new list. - int startOfDifferences = _computeStartOfDifferences(oldNodes, newNodes); - int endOfDifferencesOld = -1; - int endOfDifferencesNew = -1; - // if one of the lists are shorter than where the differences start, - // then - // then some portion of the lists are identical - if ((startOfDifferences >= oldNodes.getLength()) || (startOfDifferences >= newNodes.getLength())) { - if (oldNodes.getLength() < newNodes.getLength()) { - // Then there are new regions to add - // these lengths will cause the vector of old ones to not - // have any elements, and the vector of new regions to have - // just the new ones not in common with the old ones - //startOfDifferences should equal oldNodes.getLength(), - // calculated above on _computeStartOfDifferences - minimalOldNodes = EMPTY_LIST; - endOfDifferencesNew = newNodes.getLength() - 1; - minimalNewNodes = _formMinimumList(newNodes, startOfDifferences, endOfDifferencesNew); - } else { - if (oldNodes.getLength() > newNodes.getLength()) { - // delete old - // then there are old regions to delete - // these lengths will cause the vector of old regions to - // contain the ones to delete, and the vector of new - // regions - // not have any elements - //startOfDifferences should equal newNodes.getLength(), - // calculated above on _computeStartOfDifferences - endOfDifferencesOld = oldNodes.getLength() - 1; - minimalOldNodes = _formMinimumList(oldNodes, startOfDifferences, endOfDifferencesOld); - minimalNewNodes = EMPTY_LIST; - } else - // unlikely event - event = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace); - } - } else { - // We found a normal startOfDiffernces, but have not yet found the - // ends. - // We'll look for the end of differences by going backwards down - // the two lists. - // Here we need a seperate index for each array, since they may be - // (and - // probably are) of different lengths. - int indexOld = oldNodes.getLength() - 1; - int indexNew = newNodes.getLength() - 1; - // The greaterThanEffectedRegion is important to gaurd against - // incorrect counting - // when something identical is inserted to what's already there - // (see minimization test case 5) - // Note: the indexOld > startOfDifferences keeps indexOld from - // getting too small, - // so that the subsequent oldNodes.item(indexOld) is always valid. - while ((indexOld >= startOfDifferences) && (_greaterThanEffectedRegion(oldNodes.item(indexOld)))) { - if (!(oldNodes.item(indexOld).sameAs(newNodes.item(indexNew), fLengthDifference))) { - break; - } else { - // if they are equal, then we will be keeping the old one, - // so - // we need to be sure its parentDocument is set back to - // the - // right instance - oldNodes.item(indexOld).setParentDocument(fStructuredDocument); - } - indexOld--; - indexNew--; - } - endOfDifferencesOld = indexOld; - endOfDifferencesNew = indexNew; - minimalOldNodes = _formMinimumList(oldNodes, startOfDifferences, endOfDifferencesOld); - minimalNewNodes = _formMinimumList(newNodes, startOfDifferences, endOfDifferencesNew); - } ///////////////////////////////////////// - // - IStructuredDocumentRegion firstDownStreamNode = null; - event = regionCheck(minimalOldNodes, minimalNewNodes); - if (event != null) { - firstDownStreamNode = minimalOldNodes.item(0).getNext(); - if (firstDownStreamNode != null && fLengthDifference != 0) { // if - // firstDownStream - // is - // null, - // then - // we're - // at - // the - // end - // of - // the - // document - StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference); - } // - } else { - event = nodesReplacedCheck(minimalOldNodes, minimalNewNodes); - // now splice the new chain of nodes to where the old chain is (or - // was) - // the firstDownStreamNode (the first of those after the new - // nodes) - // is - // remembered as a tiny optimization. - if (minimalOldNodes.getLength() == 0 && minimalNewNodes.getLength() > 0) { - // if no old nodes are being deleted, then use the - // the newNodes offset (minus one) to find the point to - // update downstream nodes, and after updating downstream - // nodes postions, insert the new ones. - int insertOffset = minimalNewNodes.item(0).getStartOffset(); - IStructuredDocumentRegion lastOldUnchangedNode = null; - if (insertOffset > 0) { - lastOldUnchangedNode = fStructuredDocument.getRegionAtCharacterOffset(insertOffset - 1); - firstDownStreamNode = lastOldUnchangedNode.getNext(); - } else { - // we're inserting at very beginning - firstDownStreamNode = fStructuredDocument.getFirstStructuredDocumentRegion(); - // SIDE EFFECT: change the firstNode pointer if we're - // inserting at beginning - fStructuredDocument.setFirstDocumentRegion(minimalNewNodes.item(0)); - } - StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference); - insertNodes(lastOldUnchangedNode, firstDownStreamNode, minimalNewNodes); - // this (nodes replaced) is the only case where we need to - // update the cached Node - reSetCachedNode(minimalOldNodes, minimalNewNodes); - } else { - firstDownStreamNode = switchNodeLists(minimalOldNodes, minimalNewNodes); - // no need to adjust the length of the new nodes themselves, - // they - // are already correct, but we do need to - // adjust all "down stream" nodes with the length of the - // insertion or deletion - // --- adjustment moved to calling method. - if (firstDownStreamNode != null) { - // && event != null - StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference); - } // - // this (nodes replaced) is the only case where we need to - // update the cached Node - reSetCachedNode(minimalOldNodes, minimalNewNodes); - } - } - return event; - } - - // TODO: This should be abstract. - public IStructuredTextReParser newInstance() { - return new StructuredDocumentReParser(); - } - - protected StructuredDocumentEvent nodesReplacedCheck(CoreNodeList oldNodes, CoreNodeList newNodes) { - // actually, nothing to check here, since (and assuming) we've already - // minimized the number of nodes, and ruled out mere region changes - StructuredDocumentEvent result = new StructuredDocumentRegionsReplacedEvent(fStructuredDocument, fRequester, oldNodes, newNodes, fChanges, fStart, fLengthToReplace, fIsEntireDocument); - return result; - } - - /** - * A method to allow any heuristic "quick checks" that might cover many - * many cases, before expending the time on a full reparse. - * - */ - public StructuredDocumentEvent quickCheck() { - StructuredDocumentEvent result = null; - // if the dirty start is null, then we have an empty document. - // in which case we'll return null so everything can be - // reparsed "from scratch" . If its not null, we'll give the flatnode - // a - // chance - // to handle, but only if there is one flatnode involved. - if (dirtyStart != null && dirtyStart == dirtyEnd) { - IStructuredDocumentRegion targetNode = dirtyStart; - result = dirtyStart.updateRegion(fRequester, targetNode, fChanges, fStart, fLengthToReplace); - if (result != null) { - // at this point only, we need to update the text store and - // and downstream nodes. - // FUTURE_TO_DO: can this dependency on structuredDocument - // method be eliminated? - fStructuredDocument.updateDocumentData(fStart, fLengthToReplace, fChanges); - IStructuredDocumentRegion firstDownStreamNode = targetNode.getNext(); - // then flatnode must have been the last one, so need to - // update - // any downstream ones - if (firstDownStreamNode != null) { - StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference); - } - } - } - if (result != null) { - result.setDeletedText(fDeletedText); - } - return result; - } - - /** - * If only one node is involved, sees how many regions are changed. If - * only one, then its a 'regionChanged' event ... if more than one, its a - * 'regionsReplaced' event. - */ - protected StructuredDocumentEvent regionCheck(CoreNodeList oldNodes, CoreNodeList newNodes) { - if (Debug.debugStructuredDocument) - System.out.println("IStructuredDocument::regionsReplacedCheck"); //$NON-NLS-1$ - //$NON-NLS-1$ - //$NON-NLS-1$ - // the "regionsReplaced" event could only be true if and only if the - // nodelists - // are each only "1" in length. - StructuredDocumentEvent result = null; - int oldLength = oldNodes.getLength(); - int newLength = newNodes.getLength(); - if ((oldLength != 1) || (newLength != 1)) { - result = null; - } else { - IStructuredDocumentRegion oldNode = oldNodes.item(0); - IStructuredDocumentRegion newNode = newNodes.item(0); - result = regionCheck(oldNode, newNode); - } - return result; - } - - /** - * If only one node is involved, sees how many regions are changed. If - * only one, then its a 'regionChanged' event ... if more than one, its a - * 'regionsReplaced' event. - */ - protected StructuredDocumentEvent regionCheck(IStructuredDocumentRegion oldNode, IStructuredDocumentRegion newNode) { - // - StructuredDocumentEvent result = null; - ITextRegionList oldRegions = oldNode.getRegions(); - ITextRegionList newRegions = newNode.getRegions(); - ITextRegion[] oldRegionsArray = oldRegions.toArray(); - ITextRegion[] newRegionsArray = newRegions.toArray(); - // - // for the 'regionsReplaced' event, we don't care if - // the regions changed due to type, or text, - // we'll just collect all those that are not equal - // into the old and new region lists. - // Note: we, of course, assume that old and new regions - // are basically contiguous -- and we force it to be so, - // even if not literally so, by starting at beginning to - // find first difference, and then starting at end to find - // last difference. Everything in between we assume is different. - // - // going up is easy, we start at zero in each, and continue - // till regions are not the same. - int startOfDifferences = _computeStartOfDifferences(oldNode, oldRegions, newNode, newRegions); - int endOfDifferencesOld = -1; - int endOfDifferencesNew = -1; - // - // - // if one of the lists are shorter than where the differences start, - // then - // then some portion of the lists are identical - if ((startOfDifferences >= oldRegions.size()) || (startOfDifferences >= newRegions.size())) { - if (oldRegions.size() < newRegions.size()) { - // INSERT CASE - // then there are new regions to add - // these lengths will cause the vector of old ones to not - // have any elements, and the vector of new regions to have - // just the new ones. - startOfDifferences = oldRegionsArray.length; - endOfDifferencesOld = oldRegionsArray.length - 1; - endOfDifferencesNew = newRegionsArray.length - 1; - } else { - if (oldRegions.size() > newRegions.size()) { - // DELETE CASE - // then there are old regions to delete - // these lengths will cause the vector of old regions to - // contain the ones to delete, and the vector of new - // regions - // not have any elements - startOfDifferences = newRegionsArray.length; - endOfDifferencesOld = oldRegionsArray.length - 1; - endOfDifferencesNew = newRegionsArray.length - 1; - } else { - // else the lists are identical! - // unlikely event, probably error in current design, since - // we check for identity at the very beginning of - // reparsing. - result = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace); - } - } - } else { - if ((startOfDifferences > -1) && (endOfDifferencesOld < 0) && (endOfDifferencesNew < 0)) { - // We found a normal startOfDiffernces, but have not yet found - // the ends. - // We'll look for the end of differences by going backwards - // down the two lists. - // Here we need a seperate index for each array, since they - // may - // be (and - // probably are) of different lengths. - int indexOld = oldRegionsArray.length - 1; - int indexNew = newRegionsArray.length - 1; - while ((indexOld >= startOfDifferences) && (_greaterThanEffectedRegion(oldNode, oldRegionsArray[indexOld]))) { - if ((!(oldNode.sameAs(oldRegionsArray[indexOld], newNode, newRegionsArray[indexNew], fLengthDifference)))) { - //endOfDifferencesOld = indexOne; - //endOfDifferencesNew = indexTwo; - break; - } - indexOld--; - indexNew--; - } - endOfDifferencesOld = indexOld; - endOfDifferencesNew = indexNew; - } - } - // - // result != null means the impossible case above occurred - if (result == null) { - // Now form the two vectors of different regions - ITextRegionList holdOldRegions = new TextRegionListImpl(); - ITextRegionList holdNewRegions = new TextRegionListImpl(); - if (startOfDifferences > -1 && endOfDifferencesOld > -1) { - for (int i = startOfDifferences; i <= endOfDifferencesOld; i++) { - holdOldRegions.add(oldRegionsArray[i]); - } - } - if (startOfDifferences > -1 && endOfDifferencesNew > -1) { - for (int i = startOfDifferences; i <= endOfDifferencesNew; i++) { - holdNewRegions.add(newRegionsArray[i]); - } - } - if (holdOldRegions.size() == 0 && holdNewRegions.size() == 0) { - // then this means the regions were identical, which means - // someone - // pasted exactly the same thing they had selected, or !!! - // someone deleted the end bracket of the tag. !!!? - result = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace); - } else { - //If both holdOldRegions and holdNewRegions are of length 1, - // then its - // a "region changed" event, else a "regions replaced" event. - // so we want the new instance of region to become part of the - // old instance of old node - if ((holdOldRegions.size() == 1) && (holdNewRegions.size() == 1) && _regionsSameKind((holdNewRegions.get(0)), (holdOldRegions.get(0)))) { - ITextRegion newOldRegion = swapNewForOldRegion(oldNode, holdOldRegions.get(0), newNode, holdNewRegions.get(0)); - // -- need to update any down stream regions, within this - // 'oldNode' - updateDownStreamRegions(oldNode, newOldRegion); - result = new RegionChangedEvent(fStructuredDocument, fRequester, oldNode, newOldRegion, fChanges, fStart, fLengthToReplace); - } else { - replaceRegions(oldNode, holdOldRegions, newNode, holdNewRegions); - // -- need to update any down stream regions, within this - // 'oldNode' - // don't need with the way replaceRegions is implemented. - // It handles. - //if(holdNewRegions.size() > 0) - //updateDownStreamRegions(oldNode, (ITextRegion) - // holdNewRegions.lastElement()); - result = new RegionsReplacedEvent(fStructuredDocument, fRequester, oldNode, holdOldRegions, holdNewRegions, fChanges, fStart, fLengthToReplace); - } - } - } - return result; - } - - /** - * An entry point for reparsing. It calculates the dirty start and dirty - * end flatnodes based on the start point and length of the changes. - * - */ - public StructuredDocumentEvent reparse() { - StructuredDocumentEvent result = null; - // if we do not have a cachedNode, then the document - // must be empty, so simply use 'null' as the dirtyStart and dirtyEnd - // otherwise, find them. - if (fStructuredDocument.getCachedDocumentRegion() != null) { - findDirtyStart(fStart); - int end = fStart + fLengthToReplace; - findDirtyEnd(end); - } - if (fStructuredDocument.getCachedDocumentRegion() != null) { - result = checkHeuristics(); - } - if (result == null) { - result = reparse(dirtyStart, dirtyEnd); - } - endReParse(); - return result; - } - - /** - * An entry point for reparsing. It calculates the dirty start and dirty - * end flatnodes based on suggested positions to begin and end. This is - * needed for cases where parsing must go beyond the immediate node and - * its direct neighbors. - * - */ - protected StructuredDocumentEvent reparse(int reScanStartHint, int reScanEndHint) { - StructuredDocumentEvent result = null; - // if we do not have a cachedNode, then the document - // must be empty, so simply use 'null' as the dirtyStart and dirtyEnd - if (fStructuredDocument.getCachedDocumentRegion() != null) { - findDirtyStart(reScanStartHint); - findDirtyEnd(reScanEndHint); - } - result = reparse(dirtyStart, dirtyEnd); - isParsing = false; - // debug - //verifyStructured(result); - return result; - } - - /** - * The core reparsing method ... after the dirty start and dirty end have - * been calculated elsewhere. - */ - protected StructuredDocumentEvent reparse(IStructuredDocumentRegion dirtyStart, IStructuredDocumentRegion dirtyEnd) { - StructuredDocumentEvent result = null; - int rescanStart = -1; - int rescanEnd = -1; - boolean firstTime = false; - // - // "save" the oldNodes (that may be replaced) in a list - CoreNodeList oldNodes = formOldNodes(dirtyStart, dirtyEnd); - if (dirtyStart == null || dirtyEnd == null) { - // dirtyStart or dirty end are null, then that means we didn't - // have - // a - // cached node, which means we have an empty document, so we - // just need to rescan the changes - rescanStart = 0; - rescanEnd = fChanges.length(); - firstTime = true; - } else { - // set the start of the text to rescan - rescanStart = dirtyStart.getStart(); - // - // set the end of the text to rescan - // notice we use the same rationale as for the rescanStart, - // with the added caveat that length has to be added to it, - // to compensate for the new text which has been added or deleted. - // If changes has zero length, then "length" will be negative, - // since - // we are deleting text. Otherwise, use the difference between - // what's selected to be replaced and the length of the new text. - rescanEnd = dirtyEnd.getEnd() + fLengthDifference; - } - // now that we have the old stuff "saved" away, update the document - // with the changes. - // FUTURE_TO_DO -- don't fire "document changed" event till later - fStructuredDocument.updateDocumentData(fStart, fLengthToReplace, fChanges); - // ------------------ now the real work - result = core_reparse(rescanStart, rescanEnd, oldNodes, firstTime); - // - // event is returned to the caller, incase there is - // some opitmization they can do - return result; - } - - protected void replaceRegions(IStructuredDocumentRegion oldNode, ITextRegionList oldRegions, IStructuredDocumentRegion newNode, ITextRegionList newRegions) { - int insertPos = -1; - ITextRegionList regions = oldNode.getRegions(); - // make a fake flatnode to be new parent of oldRegions, so their text - // will be right. - //IStructuredDocumentRegion holdOldStructuredDocumentRegion = new - // BasicStructuredDocumentRegion(oldNode); - // - // need to reset the parent of the new to-be-inserted regions to be - // the - // same oldNode that is the one having its regions changed - // DW, 4/16/2003, removed since ITextRegion no longer has parent. - // ITextRegionContainer oldParent = oldNode; - // for (int i = 0; i < newRegions.size(); i++) { - // AbstractRegion region = (AbstractRegion) newRegions.elementAt(i); - // region.setParent(oldParent); - // } - // if there are no old regions, insert the new regions according to - // offset - if (oldRegions.size() == 0) { - ITextRegion firstNewRegion = newRegions.get(0); - int firstOffset = newNode.getStartOffset(firstNewRegion); - // if at beginning, insert there - if (firstOffset == 0) { - insertPos = 0; - } else { - // - ITextRegion regionAtOffset = oldNode.getRegionAtCharacterOffset(firstOffset); - if (regionAtOffset == null) - insertPos = regions.size(); - else - insertPos = regions.indexOf(regionAtOffset); - } - } else { - // else, delete old ones before inserting new ones in their place - ITextRegion firstOldRegion = oldRegions.get(0); - insertPos = regions.indexOf(firstOldRegion); - regions.removeAll(oldRegions); - } - regions.addAll(insertPos, newRegions); - // now regions vector of each node should be of equal length, - // so go through each, and make sure the old regions - // offsets matches the new regions offsets - // (we'll just assign them all, but could be slightly more effiecient) - ITextRegionList allNewRegions = newNode.getRegions(); - for (int i = 0; i < regions.size(); i++) { - ITextRegion nextOldishRegion = regions.get(i); - ITextRegion nextNewRegion = allNewRegions.get(i); - nextOldishRegion.equatePositions(nextNewRegion); - checkAndAssignParent(oldNode, nextOldishRegion); - } - oldNode.setLength(newNode.getLength()); - oldNode.setEnded(newNode.isEnded()); - oldNode.setParentDocument(newNode.getParentDocument()); - // removed concept of part of these regions, so no longer need to do. - // for (int i = 0; i < oldRegions.size(); i++) { - // ITextRegion region = (ITextRegion) oldRegions.elementAt(i); - // region.setParent(holdOldStructuredDocumentRegion); - // } - } - - private void reSetCachedNode(CoreNodeList oldNodes, CoreNodeList newNodes) { - // use the last newNode as the new cachedNode postion, unless its null - // (e.g. when nodes are deleted) in which case, assign - // it to a "safe" node so we don't lose reference to the - // structuredDocument! - if (newNodes.getLength() > 0) { - // use last new node as the cache - fStructuredDocument.setCachedDocumentRegion(newNodes.item(newNodes.getLength() - 1)); - } else { - // if cachedNode is an old node, then we're in trouble: - // we can't leave it as the cached node! and its already - // been disconnected from the model, so we can't do getNext - // or getPrevious, so we'll get one that is right before - // (or right after) the offset of the old nodes that are being - // deleted. - // - // if newNodesHead and cachedNode are both null, then - // it means we were asked to insert an empty string into - // an empty document. So we have nothing to do here - // (that is, we have no node to cache) - // similarly if there are no new nodes and no old nodes then - // nothing to do (but that should never happen ... we shouldn't - // get there if there is no event to generate). - if ((fStructuredDocument.getCachedDocumentRegion() != null) && (oldNodes.getLength() > 0)) { - // note: we can't simple use nodeAtCharacterOffset, since it - // depends on cachedNode. - if (oldNodes.includes(fStructuredDocument.getCachedDocumentRegion())) - fStructuredDocument.setCachedDocumentRegion(fStructuredDocument.getFirstStructuredDocumentRegion()); - } - if ((fStructuredDocument.getCachedDocumentRegion() == null) && (Debug.displayWarnings)) { - // this will happen now legitamately when all text is deleted - // from a document - System.out.println("Warning: StructuredDocumentReParser::reSetCachedNode: could not find a node to cache! (its ok if all text deleted)"); //$NON-NLS-1$ - } - } - } - - public void setStructuredDocument(IStructuredDocument newStructuredDocument) { - // NOTE: this method (and class) depend on being able to - // do the following cast (i.e. references some fields directly) - fStructuredDocument = (BasicStructuredDocument) newStructuredDocument; - fFindReplaceDocumentAdapter = null; - } - - private IStructuredDocumentRegion splice(CoreNodeList oldNodes, CoreNodeList newNodes) { - // - IStructuredDocumentRegion firstOld = null; - IStructuredDocumentRegion firstNew = null; - IStructuredDocumentRegion lastOld = null; - IStructuredDocumentRegion lastNew = null; - // - IStructuredDocumentRegion oldPrevious = null; - IStructuredDocumentRegion oldNext = null; - IStructuredDocumentRegion newPrevious = null; - IStructuredDocumentRegion newNext = null; - // - // if called with both arguments empty lists, we can disregard. - // this happens, for example, when some text is replaced with the - // identical text. - if ((oldNodes.getLength() == 0) && (newNodes.getLength() == 0)) { - return null; - } - // get pointers - if (newNodes.getLength() > 0) { - firstNew = newNodes.item(0); - lastNew = newNodes.item(newNodes.getLength() - 1); - } - // - if (oldNodes.getLength() > 0) { - firstOld = oldNodes.item(0); - lastOld = oldNodes.item(oldNodes.getLength() - 1); - if (firstOld != null) - oldPrevious = firstOld.getPrevious(); - if (lastOld != null) - oldNext = lastOld.getNext(); - } - // handle switch - if (newNodes.getLength() > 0) { - // switch surrounding StructuredDocumentRegions' references to - // lists - if (oldPrevious != null) - oldPrevious.setNext(firstNew); - if (newPrevious != null) - newPrevious.setNext(firstOld); - if (oldNext != null) - oldNext.setPrevious(lastNew); - if (newNext != null) - newNext.setPrevious(lastOld); - // switch list pointers to surrounding StructuredDocumentRegions - if (firstOld != null) - firstOld.setPrevious(newPrevious); - if (lastOld != null) - lastOld.setNext(newNext); - if (firstNew != null) - firstNew.setPrevious(oldPrevious); - if (lastNew != null) - lastNew.setNext(oldNext); - } else { - // short circuit when there are no new nodes - if (oldPrevious != null) - oldPrevious.setNext(oldNext); - if (oldNext != null) - oldNext.setPrevious(oldPrevious); - } - // - // SIDE EFFECTs - // if we have oldNodes, and if oldNext or oldPrevious is null, - // that means we are replacing - // the lastNode or firstNode the structuredDocuments's chain of nodes, - // so we need to update the structuredDocuments last or first Node - // as the last or first of the new nodes. - // (and sometimes even these will be null! such as when deleting all - // text in a document). - if ((oldNext == null) && (oldNodes.getLength() > 0)) { - if (newNodes.getLength() > 0) { - fStructuredDocument.setLastDocumentRegion(lastNew); - } else { - // in this case, the last node is being deleted, but not - // replaced - // with anything. In this case, we can just back up one - // from the first old node - fStructuredDocument.setLastDocumentRegion(firstOld.getPrevious()); - } - } - if ((oldPrevious == null) && (oldNodes.getLength() > 0)) { - if (newNodes.getLength() > 0) { - fStructuredDocument.setFirstDocumentRegion(firstNew); - } else { - // in this case the first node is being deleted, but not - // replaced - // with anything. So, we just go one forward past the last old - // node. - fStructuredDocument.setFirstDocumentRegion(lastOld.getNext()); - } - } - // as a tiny optimization, we return the first of the downstream - // nodes, - // if any - return oldNext; - } - - /** - * The purpose of this method is to "reuse" the old container region, when - * found to be same (so same instance doesn't change). The goal is to - * "transform" the old region, so its equivelent to the newly parsed one. - * - */ - private ITextRegion swapNewForOldRegion(IStructuredDocumentRegion oldNode, ITextRegion oldRegion, IStructuredDocumentRegion newNode, ITextRegion newRegion) { - // makes the old region instance the correct size. - oldRegion.equatePositions(newRegion); - // adjusts old node instance appropriately - oldNode.setLength(newNode.getLength()); - oldNode.setEnded(newNode.isEnded()); - // we do have to set the parent document, since the oldNode's - // were set to a temporary one, then newNode's have the - // right one. - oldNode.setParentDocument(newNode.getParentDocument()); - // if we're transforming a container region, we need to be sure to - // transfer the new embedded regions, to the old parent - // Note: if oldRegion hasEmbeddedRegions, then we know the - // newRegion does too, since we got here because they were the - // same type. - if (isCollectionRegion(oldRegion)) { // || - // hasContainerRegions(oldRegion)) - // { - transferEmbeddedRegions(oldNode, (ITextRegionContainer) oldRegion, (ITextRegionContainer) newRegion); - } - return oldRegion; - } - - private IStructuredDocumentRegion switchNodeLists(CoreNodeList oldNodes, CoreNodeList newNodes) { - IStructuredDocumentRegion result = splice(oldNodes, newNodes); - // ensure that the old nodes hold no references to the existing model - if (oldNodes.getLength() > 0) { - IStructuredDocumentRegion firstItem = oldNodes.item(0); - firstItem.setPrevious(null); - IStructuredDocumentRegion lastItem = oldNodes.item(oldNodes.getLength() - 1); - lastItem.setNext(null); - } - return result; - } - - /** - * The purpose of this method is to "reuse" the old container region, when - * found to be same (so same instance doesn't change). The goal is to - * "transform" the old region, so its equivelent to the newly parsed one. - * - */ - private void transferEmbeddedRegions(IStructuredDocumentRegion oldNode, ITextRegionContainer oldRegion, ITextRegionContainer newRegion) { - // the oldRegion should already have the right parent, since - // we got here because all's equivelent except the region - // postions have changed. - //oldRegion.setParent(newRegion.getParent()); - // but we should check if there's "nested" embedded regions, and if - // so, we can just move them over. setting their parent as this old - // region. - ITextRegionList newRegionsToTransfer = newRegion.getRegions(); - oldRegion.setRegions(newRegionsToTransfer); - Iterator newRegionsInOldOne = newRegionsToTransfer.iterator(); - while (newRegionsInOldOne.hasNext()) { - ITextRegion newOne = (ITextRegion) newRegionsInOldOne.next(); - if (isCollectionRegion(newOne)) { // || - // hasContainerRegions(newOne)) { - //((ITextRegionContainer) newOne).setParent(oldRegion); - oldRegion.setRegions(newRegion.getRegions()); - } - } - } - - private void updateDownStreamRegions(IStructuredDocumentRegion flatNode, ITextRegion lastKnownRegion) { - // so all regions after the last known region (last known to be ok) - // have to have their start and end values adjusted. - ITextRegionList regions = flatNode.getRegions(); - int listLength = regions.size(); - int startIndex = 0; - // first, loop through to find where to start - for (int i = 0; i < listLength; i++) { - ITextRegion region = regions.get(i); - if (region == lastKnownRegion) { - startIndex = i; - break; - } - } - // now, beginning one past the last known one, loop - // through to end of list, adjusting the start and end postions. - startIndex++; - for (int j = startIndex; j < listLength; j++) { - ITextRegion region = regions.get(j); - region.adjustStart(fLengthDifference); - } - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionEnumeration.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionEnumeration.java deleted file mode 100644 index 11911984e7..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionEnumeration.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - - - -import java.util.Enumeration; -import java.util.NoSuchElementException; - -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.util.Debug; - - -public class StructuredDocumentRegionEnumeration implements Enumeration { - - private int count; - private IStructuredDocumentRegion head; - private IStructuredDocumentRegion oldHead; - - /** - * StructuredDocumentRegionEnumeration constructor comment. - */ - public StructuredDocumentRegionEnumeration(IStructuredDocumentRegion newHead) { - super(); - IStructuredDocumentRegion countNode = head = newHead; - while (countNode != null) { - count++; - countNode = countNode.getNext(); - } - if (Debug.DEBUG > 5) { - System.out.println("N Nodes in StructuredDocumentRegionEnumeration Contructor: " + count); //$NON-NLS-1$ - } - } - - /** - * StructuredDocumentRegionEnumeration constructor comment. - */ - public StructuredDocumentRegionEnumeration(IStructuredDocumentRegion start, IStructuredDocumentRegion end) { - super(); - IStructuredDocumentRegion countNode = head = start; - if ((start == null) || (end == null)) { - // error condition - count = 0; - return; - } - //If both nodes are non-null, we assume there is always at least one - // item - count = 1; - while (countNode != end) { - count++; - countNode = countNode.getNext(); - } - if (org.eclipse.wst.sse.core.internal.util.Debug.DEBUG > 5) { - System.out.println("N Nodes in StructuredDocumentRegionEnumeration Contructor: " + count); //$NON-NLS-1$ - } - } - - /** - * hasMoreElements method comment. - */ - public synchronized boolean hasMoreElements() { - return count > 0; - } - - /** - * nextElement method comment. - */ - public synchronized Object nextElement() { - if (count > 0) { - count--; - oldHead = head; - head = head.getNext(); - return oldHead; - } - throw new NoSuchElementException("StructuredDocumentRegionEnumeration"); //$NON-NLS-1$ - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionIterator.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionIterator.java deleted file mode 100644 index c121b31ad0..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionIterator.java +++ /dev/null @@ -1,115 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - - - -import java.util.Vector; - -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList; -import org.eclipse.wst.sse.core.internal.util.Assert; - - -public class StructuredDocumentRegionIterator { - - public final static IStructuredDocumentRegion adjustStart(IStructuredDocumentRegion headNode, int adjustment) { - IStructuredDocumentRegion aNode = headNode; - while (aNode != null) { - aNode.adjustStart(adjustment); - aNode = aNode.getNext(); - } - return headNode; - } - - public final static int countRegions(IStructuredDocumentRegionList flatNodes) { - int result = 0; - if (flatNodes != null) { - int length = flatNodes.getLength(); - for (int i = 0; i < length; i++) { - IStructuredDocumentRegion node = flatNodes.item(i); - // don't know why, but we're getting null pointer exceptions - // in this method - if (node != null) { - result = result + node.getNumberOfRegions(); - } - } - } - return result; - } - - public final static String getText(CoreNodeList flatNodes) { - String result = null; - if (flatNodes == null) { - result = ""; //$NON-NLS-1$ - } else { - StringBuffer buff = new StringBuffer(); - //IStructuredDocumentRegion aNode = null; - int length = flatNodes.getLength(); - for (int i = 0; i < length; i++) { - buff.append(flatNodes.item(i).getText()); - } - result = buff.toString(); - } - return result; - } - - public final static CoreNodeList setParentDocument(CoreNodeList nodelist, IStructuredDocument textStore) { - Assert.isNotNull(nodelist, "nodelist was null in CoreNodeList::setTextStore(CoreNodeList, StructuredTextStore)"); //$NON-NLS-1$ - int len = nodelist.getLength(); - for (int i = 0; i < len; i++) { - IStructuredDocumentRegion node = nodelist.item(i); - //Assert.isNotNull(node, "who's putting null in the node list? in - // CoreNodeList::setTextStore(CoreNodeList, - // StructuredTextStore)"); //$NON-NLS-1$ - node.setParentDocument(textStore); - } - return nodelist; - } - - // public final static IStructuredDocumentRegion - // setStructuredDocument(IStructuredDocumentRegion headNode, - // BasicStructuredDocument structuredDocument) { - // IStructuredDocumentRegion aNode = headNode; - // while (aNode != null) { - // aNode.setParentDocument(structuredDocument); - // aNode = (IStructuredDocumentRegion) aNode.getNext(); - // } - // return headNode; - // } - public final static IStructuredDocumentRegion setParentDocument(IStructuredDocumentRegion headNode, IStructuredDocument document) { - IStructuredDocumentRegion aNode = headNode; - while (aNode != null) { - aNode.setParentDocument(document); - aNode = aNode.getNext(); - } - return headNode; - } - - public final static Vector toVector(IStructuredDocumentRegion headNode) { - IStructuredDocumentRegion aNode = headNode; - Vector v = new Vector(); - while (aNode != null) { - v.addElement(aNode); - aNode = aNode.getNext(); - } - return v; - } - - /** - * - */ - private StructuredDocumentRegionIterator() { - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentSequentialRewriteTextStore.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentSequentialRewriteTextStore.java deleted file mode 100644 index 5c31aa8094..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentSequentialRewriteTextStore.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2004 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import org.eclipse.jface.text.ITextStore; -import org.eclipse.jface.text.SequentialRewriteTextStore; - -public class StructuredDocumentSequentialRewriteTextStore extends SequentialRewriteTextStore implements CharSequence, IRegionComparible { - - /** - * @param source - */ - public StructuredDocumentSequentialRewriteTextStore(ITextStore source) { - super(source); - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#charAt(int) - */ - public char charAt(int index) { - return get(index); - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#length() - */ - public int length() { - return getLength(); - } - - /** - * @param c - * @param d - * @return - */ - private boolean matchesIgnoreCase(char c1, char c2) { - // we check both case conversions to handle those few cases, - // in languages such as Turkish, which have some characters - // which sort of have 3 cases. - boolean result = false; - if (Character.toUpperCase(c1) == Character.toUpperCase(c2)) - result = true; - else if (Character.toLowerCase(c1) == Character.toLowerCase(c2)) - result = true; - return result; - } - - public boolean regionMatches(int offset, int length, String stringToCompare) { - boolean result = false; - int compareLength = stringToCompare.length(); - if (compareLength == length) { - int endOffset = offset + length; - if (endOffset <= length()) { - result = regionMatches(offset, stringToCompare); - } - } - - return result; - } - - /** - * This method assumes all lengths have been checked and fall withint - * exceptable limits - * - * @param offset - * @param stringToCompare - * @return - */ - private boolean regionMatches(int offset, String stringToCompare) { - boolean result = true; - int stringOffset = 0; - int len = stringToCompare.length(); - for (int i = offset; i < len; i++) { - if (charAt(i) != stringToCompare.charAt(stringOffset++)) { - result = false; - break; - } - } - return result; - } - - public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) { - boolean result = false; - int compareLength = stringToCompare.length(); - if (compareLength == length) { - int endOffset = offset + length; - if (endOffset <= length()) { - result = regionMatchesIgnoreCase(offset, stringToCompare); - } - } - - return result; - } - - private boolean regionMatchesIgnoreCase(int offset, String stringToCompare) { - boolean result = true; - int stringOffset = 0; - int len = stringToCompare.length(); - for (int i = offset; i < len; i++) { - if (!matchesIgnoreCase(charAt(i), stringToCompare.charAt(stringOffset++))) { - result = false; - break; - } - } - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#subSequence(int, int) - */ - public CharSequence subSequence(int start, int end) { - - return get(start, end - start); - } - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentTextStore.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentTextStore.java deleted file mode 100644 index e825e72054..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentTextStore.java +++ /dev/null @@ -1,191 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * Viacheslav Kabanovich/Exadel 97817 Wrong algoritm in class StructuredDocumentTextStore - * https://bugs.eclipse.org/bugs/show_bug.cgi?id=97817 - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import org.eclipse.jface.text.GapTextStore; -import org.eclipse.jface.text.ITextStore; - -public class StructuredDocumentTextStore implements ITextStore, CharSequence, IRegionComparible { - - private GapTextStore fInternalStore; - - /** - * - */ - public StructuredDocumentTextStore() { - this(50, 300); - } - - /** - * @param lowWatermark - * @param highWatermark - */ - public StructuredDocumentTextStore(int lowWatermark, int highWatermark) { - super(); - fInternalStore = new GapTextStore(lowWatermark, highWatermark); - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#charAt(int) - */ - public char charAt(int index) { - return fInternalStore.get(index); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.ITextStore#get(int) - */ - public char get(int offset) { - - return fInternalStore.get(offset); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.ITextStore#get(int, int) - */ - public String get(int offset, int length) { - - return fInternalStore.get(offset, length); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.ITextStore#getLength() - */ - public int getLength() { - - return fInternalStore.getLength(); - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#length() - */ - public int length() { - - return fInternalStore.getLength(); - } - - private boolean matchesIgnoreCase(char c1, char c2) { - // we check both case conversions to handle those few cases, - // in languages such as Turkish, which have some characters - // which sort of have 3 cases. - boolean result = false; - if (Character.toUpperCase(c1) == Character.toUpperCase(c2)) - result = true; - else if (Character.toLowerCase(c1) == Character.toLowerCase(c2)) - result = true; - return result; - } - - public boolean regionMatches(int offset, int length, String stringToCompare) { - boolean result = false; - int compareLength = stringToCompare.length(); - if (compareLength == length) { - int endOffset = offset + length; - if (endOffset <= length()) { - result = regionMatches(offset, stringToCompare); - } - } - - return result; - } - - /** - * This method assumes all lengths have been checked and fall withint - * exceptable limits - * - * @param offset - * @param stringToCompare - * @return - */ - private boolean regionMatches(int offset, String stringToCompare) { - boolean result = true; - int stringOffset = 0; - int end = offset + stringToCompare.length(); - for (int i = offset; i < end; i++) { - if (charAt(i) != stringToCompare.charAt(stringOffset++)) { - result = false; - break; - } - } - return result; - } - - public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) { - boolean result = false; - int compareLength = stringToCompare.length(); - if (compareLength == length) { - int endOffset = offset + length; - if (endOffset <= length()) { - result = regionMatchesIgnoreCase(offset, stringToCompare); - } - } - - return result; - } - - private boolean regionMatchesIgnoreCase(int offset, String stringToCompare) { - boolean result = true; - int stringOffset = 0; - int end = offset + stringToCompare.length(); - for (int i = offset; i < end; i++) { - if (!matchesIgnoreCase(charAt(i), stringToCompare.charAt(stringOffset++))) { - result = false; - break; - } - } - return result; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.ITextStore#replace(int, int, - * java.lang.String) - */ - public void replace(int offset, int length, String text) { - fInternalStore.replace(offset, length, text); - - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.jface.text.ITextStore#set(java.lang.String) - */ - public void set(String text) { - fInternalStore.set(text); - - } - - /* - * (non-Javadoc) - * - * @see java.lang.CharSequence#subSequence(int, int) - */ - public CharSequence subSequence(int start, int end) { - // convert 'end' to 'length' - return fInternalStore.get(start, end - start); - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/SubSetTextStore.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/SubSetTextStore.java deleted file mode 100644 index caca8b9284..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/SubSetTextStore.java +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2004 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -/** - * This is a convience or utility class that allows you to make a copy of a - * part of a larger text store, but have the copy behave as if it was the - * larger text store. - * - * In other words, it provides a subset of a larger document, that "looks like" - * the orginal document. That is, "looks like" in terms of offsets and lengths. - * Valid access can only be made to data between the orignal offsets, even - * though those offsets are in the same units at the original, and even though - * the length appears to be long. - * - * For example, if a subsettext store is created for the def part of abcdefgh, - * then get(3,5) is valid, getLength is 8. Any other access, such as - * getChar(2), would be invalid. - */ -import org.eclipse.jface.text.ITextStore; - -/** - * Similar to basics of IDocument, but the offsets are mapped from coordinates - * of underlying storage to a "virtual" document. - */ -public class SubSetTextStore implements ITextStore { - private int pseudoBeginOffset; // maps to "zero" postion of new text - //private int pseudoEndOffset; - private int pseudoLength; // length of old/original document - private StringBuffer stringBuffer = new StringBuffer(); - - /** - * SubSetTextStore constructor comment. - * - * @param initialContent - * java.lang.String - */ - public SubSetTextStore(String initialContent, int beginOffset, int endOffset, int originalDocumentLength) { - super(); - pseudoBeginOffset = beginOffset; - //pseudoEndOffset = endOffset; - // used to be originalDocument.getLength ... not sure if used, or - // which - // is right - pseudoLength = originalDocumentLength; - stringBuffer = new StringBuffer(initialContent); - //set(initialContent); - } - - // this is our "private" get, which methods in this class should - // use to get using "real" coordinates of underlying representation. - private String _get(int begin, int length) { - char[] chars = new char[length]; - int srcEnd = begin + length; - stringBuffer.getChars(begin, srcEnd, chars, 0); - return new String(chars); - } - - public char get(int offset) { - return stringBuffer.charAt(offset - pseudoBeginOffset); - } - - /** - * @return java.lang.String - * @param begin - * int - * @param end - * int - */ - public String get(int begin, int length) { - // remap the begin and end to "appear" to be in the - // same coordinates of the original parentDocument - return _get(begin - pseudoBeginOffset, length); - } - - /** - * @return java.lang.String - * @param begin - * int - * @param end - * int - */ - public char getChar(int pos) { - // remap the begin and end to "appear" to be in the - // same coordinates of the original parentDocument - return get(pos - pseudoBeginOffset); - } - - /** - * We redefine getLength so its not the true length of this sub-set - * document, but the length of the original. This is needed, as a simple - * example, if you want to see if the pseudo end is equal the last - * position of the original document. - */ - public int getLength() { - return pseudoLength; - } - - /** - * Returns the length as if considered a true, standalone document - */ - public int getTrueLength() { - return stringBuffer.length(); - } - - public void replace(int begin, int length, String changes) { - // remap the begin and end to "appear" to be in the - // same coordinates of the original parentDocument - int end = begin + length; - stringBuffer.replace(begin - pseudoBeginOffset, end, changes); - } - - public void set(String text) { - stringBuffer.setLength(0); - stringBuffer.append(text); - } -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/TextRegionListImpl.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/TextRegionListImpl.java deleted file mode 100644 index 9f62b78323..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/TextRegionListImpl.java +++ /dev/null @@ -1,236 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2010 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * David Carver (Intalio) - bug 300434 - Make inner classes static where possible - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; - - -public class TextRegionListImpl implements ITextRegionList { - - static private class NullIterator implements Iterator { - public NullIterator() { - } - - public boolean hasNext() { - return false; - } - - public Object next() { - throw new NoSuchElementException(); - } - - public void remove() { - throw new UnsupportedOperationException("can not remove regions via iterator"); //$NON-NLS-1$ - - } - - } - - private static class RegionIterator implements Iterator { - private ITextRegion[] fIteratorRegions; - private int index = -1; - private int maxindex = -1; - - public RegionIterator(ITextRegion[] regions) { - fIteratorRegions = regions; - maxindex = fIteratorRegions.length - 1; - } - - public boolean hasNext() { - return index < maxindex; - } - - public Object next() { - if (!(index < maxindex)) - throw new NoSuchElementException(); - return fIteratorRegions[++index]; - } - - public void remove() { - if (index < 0) { - // next() has never been called - throw new IllegalStateException("can not remove regions without prior invocation of next()"); //$NON-NLS-1$ - } - throw new UnsupportedOperationException("can not remove regions via iterator"); //$NON-NLS-1$ - } - - } - - private final static int growthConstant = 2; - - private ITextRegion[] fRegions; - private int fRegionsCount = 0; - - public TextRegionListImpl() { - super(); - } - - public TextRegionListImpl(ITextRegionList regionList) { - this(); - fRegions = (ITextRegion[]) regionList.toArray().clone(); - fRegionsCount = fRegions.length; - } - - public boolean add(ITextRegion region) { - if (region == null) - return false; - ensureCapacity(fRegionsCount + 1); - fRegions[fRegionsCount++] = region; - return true; - } - - public boolean addAll(int insertPos, ITextRegionList newRegionList) { - // beginning of list is 0 to insertPos-1 - // remainder of list is insertPos to fRegionsCount - // resulting total will be be fRegionsCount + newRegions.size() - if (insertPos < 0 || insertPos > fRegionsCount) { - throw new ArrayIndexOutOfBoundsException(insertPos); - } - - int newRegionListSize = newRegionList.size(); - - ensureCapacity(fRegionsCount + newRegionListSize); - - int numMoved = fRegionsCount - insertPos; - if (numMoved > 0) - System.arraycopy(fRegions, insertPos, fRegions, insertPos + newRegionListSize, numMoved); - - if (newRegionList instanceof TextRegionListImpl && ((TextRegionListImpl) newRegionList).fRegions != null) { - System.arraycopy(((TextRegionListImpl) newRegionList).fRegions, 0, fRegions, insertPos, newRegionListSize); - } - else { - for (int i = 0; i < newRegionListSize; i++) { - fRegions[insertPos++] = newRegionList.get(i); - } - } - fRegionsCount += newRegionListSize; - return newRegionListSize != 0; - } - - public void clear() { - // note: size of array is not reduced! - fRegionsCount = 0; - } - - private void ensureCapacity(int needed) { - if (fRegions == null) { - // first time - fRegions = new ITextRegion[needed]; - return; - } - int oldLength = fRegions.length; - if (oldLength < needed) { - ITextRegion[] oldAdapters = fRegions; - ITextRegion[] newAdapters = new ITextRegion[needed + growthConstant]; - System.arraycopy(oldAdapters, 0, newAdapters, 0, fRegionsCount); - fRegions = newAdapters; - } - } - - public ITextRegion get(int index) { - // fRegionCount may not equal fRegions.length - if (index < 0 || index >= fRegionsCount) { - throw new ArrayIndexOutOfBoundsException(index); - } - return fRegions[index]; - } - - public int indexOf(ITextRegion region) { - int result = -1; - if (region != null) { - if (fRegions != null) { - for (int i = 0; i < fRegions.length; i++) { - if (region.equals(fRegions[i])) { - result = i; - break; - } - } - } - } - return result; - } - - public boolean isEmpty() { - return fRegionsCount == 0; - } - - public Iterator iterator() { - if (size() == 0) { - return new NullIterator(); - } else { - return new RegionIterator(toArray()); - } - } - - public ITextRegion remove(int index) { - // much more efficient ways to implement this, but - // I doubt if called often - ITextRegion oneToRemove = get(index); - remove(oneToRemove); - return oneToRemove; - } - - public void remove(ITextRegion a) { - if (fRegions == null || a == null) - return; - int newIndex = 0; - ITextRegion[] newRegions = new ITextRegion[fRegionsCount]; - int oldRegionCount = fRegionsCount; - boolean found = false; - for (int oldIndex = 0; oldIndex < oldRegionCount; oldIndex++) { - ITextRegion candidate = fRegions[oldIndex]; - if (a == candidate) { - fRegionsCount--; - found = true; - } else - newRegions[newIndex++] = fRegions[oldIndex]; - } - if (found) - fRegions = newRegions; - } - - public void removeAll(ITextRegionList regionList) { - // much more efficient ways to implement this, but - // I doubt if called often - if (regionList != null) { - for (int i = 0; i < regionList.size(); i++) { - this.remove(regionList.get(i)); - } - } - - } - - public int size() { - return fRegionsCount; - } - - public ITextRegion[] toArray() { - // return "clone" of internal array - ITextRegion[] newArray = new ITextRegion[fRegionsCount]; - System.arraycopy(fRegions, 0, newArray, 0, fRegionsCount); - return newArray; - } - - public void trimToSize() { - if (fRegions.length > fRegionsCount) { - ITextRegion[] newRegions = new ITextRegion[fRegionsCount]; - System.arraycopy(fRegions, 0, newRegions, 0, fRegionsCount); - fRegions = newRegions; - } - } - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredRegion.java deleted file mode 100644 index f12b76ab49..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredRegion.java +++ /dev/null @@ -1,27 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text.rules; - -import org.eclipse.jface.text.IRegion; - -/** - * Like super class except allows length and offset to be modified. This is - * convenient for some algorithms, and allows region objects to be reused. - * Note: There MIGHT be some code that assumes regions are immutable. This - * class would not be appropriate for those uses. - */ -public interface IStructuredRegion extends IRegion { - void setLength(int length); - - void setOffset(int offset); -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredTypedRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredTypedRegion.java deleted file mode 100644 index 1ea21a9851..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredTypedRegion.java +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text.rules; - -import org.eclipse.jface.text.ITypedRegion; - -/** - * Similar to extended interface, except it allows the length, offset, and - * type to be set. This is useful when iterating through a number of "small" - * regions, that all map to the the same partion regions. - */ -public interface IStructuredTypedRegion extends IStructuredRegion, ITypedRegion { - void setType(String partitionType); -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredRegion.java deleted file mode 100644 index 4ca1ded47b..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredRegion.java +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text.rules; - -import org.eclipse.jface.text.IRegion; - - - -/** - * Similar to jface region except we wanted a setting on length - */ -public class SimpleStructuredRegion implements IStructuredRegion { - /** The region length */ - private int fLength; - - /** The region offset */ - private int fOffset; - - /** - * Create a new region. - * - * @param offset - * the offset of the region - * @param length - * the length of the region - */ - public SimpleStructuredRegion(int offset, int length) { - fOffset = offset; - fLength = length; - } - - /** - * Two regions are equal if they have the same offset and length. - * - * @see Object#equals - */ - public boolean equals(Object o) { - if (o instanceof IRegion) { - IRegion r = (IRegion) o; - return r.getOffset() == fOffset && r.getLength() == fLength; - } - return false; - } - - /* - * @see IRegion#getLength - */ - public int getLength() { - return fLength; - } - - /* - * @see IRegion#getOffset - */ - public int getOffset() { - return fOffset; - } - - /** - * @see Object#hashCode hascode is overridden since we provide our own - * equals. - */ - public int hashCode() { - return (fOffset << 24) | (fLength << 16); - } - - /** - * Sets the length. - * - * @param length - * The length to set - */ - public void setLength(int length) { - fLength = length; - } - - public void setOffset(int offset) { - fOffset = offset; - } - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredTypedRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredTypedRegion.java deleted file mode 100644 index 1822a8a4d8..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredTypedRegion.java +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2005 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text.rules; - - - - -/** - * Similar jace TypedRegion, but had to subclass our version which allowed - * length to be set. - */ -public class SimpleStructuredTypedRegion extends SimpleStructuredRegion implements IStructuredTypedRegion { - - /** The region's type */ - private String fType; - - /** - * Creates a typed region based on the given specification. - * - * @param offset - * the region's offset - * @param length - * the region's length - * @param type - * the region's type - */ - public SimpleStructuredTypedRegion(int offset, int length, String type) { - super(offset, length); - fType = type; - } - - /** - * Two typed positions are equal if they have the same offset, length, and - * type. - * - * @see Object#equals - */ - public boolean equals(Object o) { - if (o instanceof SimpleStructuredTypedRegion) { - SimpleStructuredTypedRegion r = (SimpleStructuredTypedRegion) o; - return super.equals(r) && ((fType == null && r.getType() == null) || fType.equals(r.getType())); - } - return false; - } - - /* - * @see ITypedRegion#getType() - */ - public String getType() { - return fType; - } - - /* - * @see Object#hashCode - */ - public int hashCode() { - int type = fType == null ? 0 : fType.hashCode(); - return super.hashCode() | type; - } - - public void setType(String type) { - fType = type; - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - StringBuffer s = new StringBuffer(); - s.append(getOffset()); - s.append(":"); //$NON-NLS-1$ - s.append(getLength()); - s.append(" - "); //$NON-NLS-1$ - s.append(getType()); - return s.toString(); - } - -} diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/StructuredTextPartitioner.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/StructuredTextPartitioner.java deleted file mode 100644 index 14e9b1532b..0000000000 --- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/StructuredTextPartitioner.java +++ /dev/null @@ -1,651 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2010 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 - * Jens Lukowski/Innoopract - initial renaming/restructuring - * - *******************************************************************************/ -package org.eclipse.wst.sse.core.internal.text.rules; - - - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import org.eclipse.jface.text.DocumentEvent; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IDocumentPartitioner; -import org.eclipse.jface.text.ITypedRegion; -import org.eclipse.wst.sse.core.internal.ltk.parser.IBlockedStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.parser.ForeignRegion; -import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextPartitioner; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; -import org.eclipse.wst.sse.core.text.IStructuredPartitions; - - -/** - * Base Document partitioner for StructuredDocuments. BLOCK_TEXT ITextRegions - * have a partition type of BLOCK or BLOCK:TAGNAME if a surrounding tagname - * was recorded. - * - * Subclasses should synchronize access to <code>internalReusedTempInstance</code> using the lock - * <code>PARTITION_LOCK</code>. - */ -public class StructuredTextPartitioner implements IDocumentPartitioner, IStructuredTextPartitioner { - - static class CachedComputedPartitions { - int fLength; - int fOffset; - ITypedRegion[] fPartitions; - boolean isInValid; - - CachedComputedPartitions(int offset, int length, ITypedRegion[] partitions) { - fOffset = offset; - fLength = length; - fPartitions = partitions; - isInValid = true; - } - } - - private CachedComputedPartitions cachedPartitions = new CachedComputedPartitions(-1, -1, null); - protected String[] fSupportedTypes = null; - protected IStructuredTypedRegion internalReusedTempInstance = new SimpleStructuredTypedRegion(0, 0, IStructuredPartitions.DEFAULT_PARTITION); - protected IStructuredDocument fStructuredDocument; - - protected final Object PARTITION_LOCK = new Object(); - - /** - * StructuredTextPartitioner constructor comment. - */ - public StructuredTextPartitioner() { - super(); - } - - /** - * Returns the partitioning of the given range of the connected document. - * There must be a document connected to this partitioner. - * - * Note: this shouldn't be called directly by clients, unless they control - * the threading that includes modifications to the document. Otherwise - * the document could be modified while partitions are being computed. We - * advise that clients use the computePartitions API directly from the - * document, so they won't have to worry about that. - * - * @param offset - * the offset of the range of interest - * @param length - * the length of the range of interest - * @return the partitioning of the range - */ - public ITypedRegion[] computePartitioning(int offset, int length) { - if (fStructuredDocument == null) { - throw new IllegalStateException("document partitioner is not connected"); //$NON-NLS-1$ - } - ITypedRegion[] results = null; - - synchronized (cachedPartitions) { - if ((!cachedPartitions.isInValid) && (offset == cachedPartitions.fOffset) && (length == cachedPartitions.fLength)) - results = cachedPartitions.fPartitions; - } - - if (results == null) { - if (length == 0) { - results = new ITypedRegion[]{getPartition(offset)}; - } else { - List list = new ArrayList(); - int endPos = offset + length; - if (endPos > fStructuredDocument.getLength()) { - // This can occur if the model instance is being - // changed - // and everyone's not yet up to date - return new ITypedRegion[]{createPartition(offset, length, getUnknown())}; - } - int currentPos = offset; - IStructuredTypedRegion previousPartition = null; - while (currentPos < endPos) { - IStructuredTypedRegion partition = null; - synchronized (PARTITION_LOCK) { - internalGetPartition(currentPos, false); - currentPos += internalReusedTempInstance.getLength(); - - // check if this partition just continues last one - // (type is the same), - // if so, just extend length of last one, not need to - // create new - // instance. - if (previousPartition != null && internalReusedTempInstance.getType().equals(previousPartition.getType())) { - // same partition type - previousPartition.setLength(previousPartition.getLength() + internalReusedTempInstance.getLength()); - } - else { - // not the same, so add to list - partition = createNewPartitionInstance(); - } - } - if (partition != null) { - list.add(partition); - // and make current, previous - previousPartition = partition; - } - } - results = new ITypedRegion[list.size()]; - list.toArray(results); - } - if (results.length > 0) { - // truncate returned results to requested range - if (results[0].getOffset() < offset && results[0] instanceof IStructuredRegion) { - ((IStructuredRegion) results[0]).setOffset(offset); - } - int lastEnd = results[results.length - 1].getOffset() + results[results.length - 1].getLength(); - if (lastEnd > offset + length && results[results.length - 1] instanceof IStructuredRegion) { - ((IStructuredRegion) results[results.length - 1]).setLength(offset + length - results[results.length - 1].getOffset()); - } - } - synchronized (cachedPartitions) { - cachedPartitions.fLength = length; - cachedPartitions.fOffset = offset; - cachedPartitions.fPartitions = results; - cachedPartitions.isInValid = false; - } - } - return results; - } - - private void invalidatePartitionCache() { - synchronized (cachedPartitions) { - cachedPartitions.isInValid = true; - } - } - - /** - * Connects the document to the partitioner, i.e. indicates the begin of - * the usage of the receiver as partitioner of the given document. - */ - public synchronized void connect(IDocument document) { - if (document instanceof IStructuredDocument) { - invalidatePartitionCache(); - this.fStructuredDocument = (IStructuredDocument) document; - } else { - throw new IllegalArgumentException("This class and API are for Structured Documents only"); //$NON-NLS-1$ - } - } - - /** - * Determines if the given ITextRegionContainer itself contains another - * ITextRegionContainer - * - * @param ITextRegionContainer - * @return boolean - */ - protected boolean containsEmbeddedRegion(IStructuredDocumentRegion container) { - boolean containsEmbeddedRegion = false; - - ITextRegionList regions = container.getRegions(); - for (int i = 0; i < regions.size(); i++) { - ITextRegion region = regions.get(i); - if (region instanceof ITextRegionContainer) { - containsEmbeddedRegion = true; - break; - } - } - return containsEmbeddedRegion; - } - - private IStructuredTypedRegion createNewPartitionInstance() { - synchronized (PARTITION_LOCK) { - return new SimpleStructuredTypedRegion(internalReusedTempInstance.getOffset(), internalReusedTempInstance.getLength(), internalReusedTempInstance.getType()); - } - } - - /** - * Creates the concrete partition from the given values. Returns a new - * instance for each call. - * - * Subclasses may override. - * - * @param offset - * @param length - * @param type - * @return ITypedRegion - * - * TODO: should be protected - */ - public IStructuredTypedRegion createPartition(int offset, int length, String type) { - return new SimpleStructuredTypedRegion(offset, length, type); - } - - /** - * Disconnects the document from the partitioner, i.e. indicates the end - * of the usage of the receiver as partitioner of the given document. - * - * @see org.eclipse.jface.text.IDocumentPartitioner#disconnect() - */ - public synchronized void disconnect() { - invalidatePartitionCache(); - this.fStructuredDocument = null; - } - - /** - * Informs about a forthcoming document change. - * - * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent) - */ - public void documentAboutToBeChanged(DocumentEvent event) { - invalidatePartitionCache(); - } - - /** - * The document has been changed. The partitioner updates the set of - * regions and returns whether the structure of the document partitioning - * has been changed, i.e. whether partitions have been added or removed. - * - * @see org.eclipse.jface.text.IDocumentPartitioner#documentChanged(DocumentEvent) - */ - public boolean documentChanged(DocumentEvent event) { - boolean result = false; - if (event instanceof StructuredDocumentRegionsReplacedEvent) { - // partitions don't always change while document regions do, - // but that's the only "quick check" we have. - // I'm not sure if something more sophisticated will be needed - // in the future. (dmw, 02/18/04). - result = true; - } - return result; - } - - protected boolean doParserSpecificCheck(int offset, boolean partitionFound, IStructuredDocumentRegion sdRegion, IStructuredDocumentRegion previousStructuredDocumentRegion, ITextRegion next, ITextRegion previousStart) { - // this (conceptually) abstract method is not concerned with - // specific region types - return false; - } - - /** - * Returns the content type of the partition containing the given - * character position of the given document. The document has previously - * been connected to the partitioner. - * - * @see org.eclipse.jface.text.IDocumentPartitioner#getContentType(int) - */ - public String getContentType(int offset) { - return getPartition(offset).getType(); - } - - /** - * To be used by default! - */ - public String getDefaultPartitionType() { - - return IStructuredPartitions.DEFAULT_PARTITION; - } - - /** - * Returns the set of all possible content types the partitioner supports. - * I.e. Any result delivered by this partitioner may not contain a content - * type which would not be included in this method's result. - * - * @see org.eclipse.jface.text.IDocumentPartitioner#getLegalContentTypes() - */ - public java.lang.String[] getLegalContentTypes() { - if (fSupportedTypes == null) { - initLegalContentTypes(); - } - return fSupportedTypes; - } - - /** - * Returns the partition containing the given character position of the - * given document. The document has previously been connected to the - * partitioner. - * - * Note: this shouldn't be called directly by clients, unless they control - * the threading that includes modifications to the document. Otherwise - * the document could be modified while partitions are being computed. We - * advise that clients use the getPartition API directly from the - * document, so they won't have to worry about that. - * - * - * - * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int) - */ - public ITypedRegion getPartition(int offset) { - internalGetPartition(offset, true); - return createNewPartitionInstance(); - } - - protected String getPartitionFromBlockedText(ITextRegion region, int offset, String result) { - // parser sensitive code was moved to subclass for quick transition - // this (conceptually) abstract version isn't concerned with blocked - // text - - return result; - } - - protected String getPartitionType(ForeignRegion region, int offset) { - String tagname = region.getSurroundingTag(); - String result = null; - if (tagname != null) { - result = "BLOCK:" + tagname.toUpperCase(Locale.ENGLISH); //$NON-NLS-1$ - } else { - result = "BLOCK"; //$NON-NLS-1$ - } - return result; - } - - - protected String getPartitionType(IBlockedStructuredDocumentRegion blockedStructuredDocumentRegion, int offset) { - String result = null; - ITextRegionList regions = blockedStructuredDocumentRegion.getRegions(); - - // regions should never be null, or hold zero regions, but just in - // case... - if (regions != null && regions.size() > 0) { - if (regions.size() == 1) { - // if only one, then its a "pure" blocked note. - // if more than one, then must contain some embedded region - // container - ITextRegion blockedRegion = regions.get(0); - // double check for code safefy, though should always be true - if (blockedRegion instanceof ForeignRegion) { - result = getPartitionType((ForeignRegion) blockedRegion, offset); - } - } else { - // must have some embedded region container, so we'll make - // sure we'll get the appropriate one - result = getReleventRegionType(blockedStructuredDocumentRegion, offset); - } - } - return result; - } - - /** - * Method getPartitionType. - * - * @param region - * @return String - */ - private String getPartitionType(ITextRegion region) { - // if it get's to this "raw" level, then - // must be default. - return getDefaultPartitionType(); - } - - /** - * Returns the partition based on region type. This basically maps from - * one region-type space to another, higher level, region-type space. - * - * @param region - * @param offset - * @return String - */ - public String getPartitionType(ITextRegion region, int offset) { - String result = getDefaultPartitionType(); - // if (region instanceof ContextRegionContainer) { - // result = getPartitionType((ITextRegionContainer) region, offset); - // } else { - if (region instanceof ITextRegionContainer) { - result = getPartitionType((ITextRegionContainer) region, offset); - } - - result = getPartitionFromBlockedText(region, offset, result); - - return result; - - } - - /** - * Similar to method with 'ITextRegion' as argument, except for - * RegionContainers, if it has embedded regions, then we need to drill - * down and return DocumentPartition based on "lowest level" region type. - * For example, in <body id=" <%= object.getID() %>" > The text between - * <%= and %> would be a "java region" not an "HTML region". - */ - protected String getPartitionType(ITextRegionContainer region, int offset) { - // TODO this method needs to be 'cleaned up' after refactoring - // its instanceof logic seems messed up now. - String result = null; - if (region != null) { - ITextRegion coreRegion = region; - if (coreRegion instanceof ITextRegionContainer) { - result = getPartitionType((ITextRegionContainer) coreRegion, ((ITextRegionContainer) coreRegion).getRegions(), offset); - } else { - result = getPartitionType(region); - } - } else { - result = getPartitionType((ITextRegion) region, offset); - } - - return result; - } - - private String getPartitionType(ITextRegionContainer coreRegion, ITextRegionList regions, int offset) { - String result = null; - for (int i = 0; i < regions.size(); i++) { - ITextRegion region = regions.get(i); - if (coreRegion.containsOffset(region, offset)) { - result = getPartitionType(region, offset); - break; - } - } - return result; - } - - /** - * Computes the partition type for the zero-length partition between a - * start tag and end tag with the given name regions. - * - * @param previousStartTagNameRegion - * @param nextEndTagNameRegion - * @return String - */ - public String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, IStructuredDocumentRegion nextNode) { - return getDefaultPartitionType(); - } - - /** - * Return the ITextRegion at the given offset. For most cases, this will - * be the flatNode itself. Should it contain an embedded - * ITextRegionContainer, will return the internal region at the offset - * - * - * @param flatNode - * @param offset - * @return ITextRegion - */ - private String getReleventRegionType(IStructuredDocumentRegion flatNode, int offset) { - // * Note: the original form of this method -- which returned "deep" - // region, isn't that - // * useful, after doing parent elimination refactoring, - // * since once the deep region is returned, its hard to get its text - // or offset without - // * proper parent. - ITextRegion resultRegion = null; - if (containsEmbeddedRegion(flatNode)) { - resultRegion = flatNode.getRegionAtCharacterOffset(offset); - if (resultRegion instanceof ITextRegionContainer) { - resultRegion = flatNode.getRegionAtCharacterOffset(offset); - ITextRegionList regions = ((ITextRegionContainer) resultRegion).getRegions(); - for (int i = 0; i < regions.size(); i++) { - ITextRegion region = regions.get(i); - if (flatNode.getStartOffset(region) <= offset && offset < flatNode.getEndOffset(region)) { - resultRegion = region; - break; - } - } - } - } else { - resultRegion = flatNode; - } - return resultRegion.getType(); - } - - /** - * To be used, instead of default, when there is some thing surprising - * about are attempt to partition - */ - protected String getUnknown() { - return IStructuredPartitions.UNKNOWN_PARTITION; - } - - /** - * to be abstract eventually - */ - protected void initLegalContentTypes() { - fSupportedTypes = new String[]{IStructuredPartitions.DEFAULT_PARTITION, IStructuredPartitions.UNKNOWN_PARTITION}; - } - - /** - * Returns the partition containing the given character position of the - * given document. The document has previously been connected to the - * partitioner. If the checkBetween parameter is true, an offset between a - * start and end tag will return a zero-length region. - */ - private void internalGetPartition(int offset, boolean checkBetween) { - if (fStructuredDocument == null) { - throw new IllegalStateException("document partitioner is not connected"); //$NON-NLS-1$ - } - - boolean partitionFound = false; - int docLength = fStructuredDocument.getLength(); - // get document region type and map to partition type : - // Note: a partion can be smaller than a flatnode, if that flatnode - // contains a region container. - // That's why we need to get "relevent region". - IStructuredDocumentRegion structuredDocumentRegion = fStructuredDocument.getRegionAtCharacterOffset(offset); - // flatNode is null if empty document - // this is king of a "normal case" for empty document - if (structuredDocumentRegion == null) { - if (docLength == 0) { - /* - * In order to prevent infinite error loops, this partition - * must never have a zero length unless the document is also - * zero length - */ - setInternalPartition(offset, 0, getDefaultPartitionType()); - partitionFound = true; - } - else { - /* - * This case is "unusual". When would region be null, and - * document longer than 0. I think this means something's "out - * of sync". And we may want to "flag" that fact and just - * return one big region of 'unknown', instead of one - * character at a time. - */ - setInternalPartition(offset, 1, getUnknown()); - partitionFound = true; - } - } - else if (checkBetween) { - // dmw: minimizes out to the first if test above - // if (structuredDocumentRegion == null && docLength == 0) { - // // known special case for an empty document - // setInternalPartition(offset, 0, getDefault()); - // partitionFound = true; - // } - // else - if (structuredDocumentRegion.getStartOffset() == offset) { - IStructuredDocumentRegion previousStructuredDocumentRegion = structuredDocumentRegion.getPrevious(); - if (previousStructuredDocumentRegion != null) { - ITextRegion next = structuredDocumentRegion.getRegionAtCharacterOffset(offset); - ITextRegion previousStart = previousStructuredDocumentRegion.getRegionAtCharacterOffset(previousStructuredDocumentRegion.getStartOffset()); - partitionFound = doParserSpecificCheck(offset, partitionFound, structuredDocumentRegion, previousStructuredDocumentRegion, next, previousStart); - } - } - } - - if (!partitionFound && structuredDocumentRegion != null) { - /* We want the actual ITextRegion and not a possible ITextRegionCollection that - * could be returned by IStructuredDocumentRegion#getRegionAtCharacterOffset - * This allows for correct syntax highlighting and content assist. - */ - DeepRegion resultRegion = getDeepRegionAtCharacterOffset(structuredDocumentRegion, offset); - partitionFound = isDocumentRegionBasedPartition(structuredDocumentRegion, resultRegion.region, offset); - if (!partitionFound) { - if (resultRegion.region != null) { - String type = getPartitionType(resultRegion.region, offset); - setInternalPartition(offset, resultRegion.end - offset, type); - } else { - // can happen at EOF - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=224886 - // The unknown type was causing problems with content assist in JSP documents - setInternalPartition(offset, 1, getDefaultPartitionType()); - } - } - } - } - - private static class DeepRegion { - int end; - ITextRegion region; - DeepRegion(ITextRegion r, int e) { - region = r; - end = e; - } - } - - /** - * <p>Unlike {@link IStructuredDocumentRegion#getRegionAtCharacterOffset(int)} this will dig - * into <code>ITextRegionCollection</code> to find the region containing the given offset</p> - * - * @param region the containing region of the given <code>offset</code> - * @param offset to the overall offset in the document. - * @return the <code>ITextRegion</code> containing the given <code>offset</code>, will never be - * a <code>ITextRegionCollextion</code> - */ - private DeepRegion getDeepRegionAtCharacterOffset(IStructuredDocumentRegion region, int offset) { - ITextRegion text = region.getRegionAtCharacterOffset(offset); - int end = region.getStartOffset(); - if (text != null) - end += text.getStart(); - while (text instanceof ITextRegionCollection) { - text = ((ITextRegionCollection) text).getRegionAtCharacterOffset(offset); - end += text.getStart(); - } - if (text != null) - end += text.getLength(); - return new DeepRegion(text, end); - } - - /** - * Provides for a per-StructuredDocumentRegion override selecting the - * partition type using more than just a single ITextRegion. - * - * @param structuredDocumentRegion - * the StructuredDocumentRegion - * @param containedChildRegion - * an ITextRegion within the given StructuredDocumentRegion - * that would normally determine the partition type by itself - * @param offset - * the document offset - * @return true if the partition type will be overridden, false to - * continue normal processing - */ - protected boolean isDocumentRegionBasedPartition(IStructuredDocumentRegion structuredDocumentRegion, ITextRegion containedChildRegion, int offset) { - return false; - } - - public IDocumentPartitioner newInstance() { - return new StructuredTextPartitioner(); - } - - protected void setInternalPartition(int offset, int length, String type) { - synchronized (PARTITION_LOCK) { - internalReusedTempInstance.setOffset(offset); - internalReusedTempInstance.setLength(length); - internalReusedTempInstance.setType(type); - } - } - -} |