[154899] DirtyRegionProcessor#contains is called a lot
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DirtyRegionProcessor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DirtyRegionProcessor.java
index f9166fd..4bdfe29 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DirtyRegionProcessor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/DirtyRegionProcessor.java
@@ -211,18 +211,20 @@
* @param resource
*/
private synchronized void addRequest(DirtyRegion newDirtyRegion) {
+ // NOTE: This method is called a lot so make sure it's fast
List dirtyRegionQueue = getDirtyRegionQueue();
- // if we already have a request which contains the new request,
- // discare the new request
- int size = dirtyRegionQueue.size();
- for (int i = 0; i < size; i++) {
- if (contains((DirtyRegion) dirtyRegionQueue.get(i), newDirtyRegion))
- return;
- }
- // if new request is contains any existing requests,
- // remove those
for (Iterator it = dirtyRegionQueue.iterator(); it.hasNext();) {
- if (contains(newDirtyRegion, (DirtyRegion) it.next()))
+ // go through list of existing dirty regions and check if any
+ // dirty regions need to be discarded
+ DirtyRegion currentExisting = (DirtyRegion) it.next();
+ DirtyRegion outer = getOuterRegion(currentExisting, newDirtyRegion);
+ // if we already have a request which contains the new request,
+ // discard the new request
+ if (outer == currentExisting)
+ return;
+ // if new request contains any existing requests,
+ // remove those
+ if (outer == newDirtyRegion)
it.remove();
}
dirtyRegionQueue.add(newDirtyRegion);
@@ -273,14 +275,31 @@
}
/**
+ * Used to determine if one dirty region contains the other and if so,
+ * which is the one that contains it.
+ *
+ * @param root
+ * @param possible
+ * @return the outer dirty region if it contains the other dirty region,
+ * null otherwise
+ */
+ protected DirtyRegion getOuterRegion(DirtyRegion root, DirtyRegion possible) {
+ DirtyRegion outer = null;
+ if (isContained(root, possible))
+ outer = root;
+ else if (isContained(possible, root))
+ outer = possible;
+ return outer;
+ }
+
+ /**
* Used to determine of a "possible" dirty region can be discarded in
* favor of using just the "root" dirty region.
*
* @return if the root dirty region contains possible, return true,
* otherwise return false
*/
- protected boolean contains(DirtyRegion root, DirtyRegion possible) {
-
+ private boolean isContained(DirtyRegion root, DirtyRegion possible) {
int rootStart = root.getOffset();
int rootEnd = rootStart + root.getLength();
int possStart = possible.getOffset();
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java
index b93bf19..270f397 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java
@@ -86,42 +86,102 @@
private IModelLifecycleListener fLifeCycleListener = new ModelLifecycleListener();
- /**
- * @see org.eclipse.wst.sse.ui.internal.reconcile.DirtyRegionProcessor#contains(org.eclipse.jface.text.reconciler.DirtyRegion,
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.wst.sse.ui.internal.reconcile.DirtyRegionProcessor#getOuterRegion(org.eclipse.jface.text.reconciler.DirtyRegion,
* org.eclipse.jface.text.reconciler.DirtyRegion)
*/
- protected boolean contains(DirtyRegion root, DirtyRegion possible) {
- // this method is a performance hit
- // look for alternatives
-
- boolean contains = false;
- IStructuredModel sModel = getStructuredModelForRead(getDocument());
- try {
- if (sModel != null) {
- IndexedRegion rootRegion = sModel.getIndexedRegion(root.getOffset());
- IndexedRegion rootRegion2 = sModel.getIndexedRegion(root.getOffset() + root.getLength());
- IndexedRegion possRegion = sModel.getIndexedRegion(possible.getOffset());
- IndexedRegion possRegion2 = sModel.getIndexedRegion(possible.getOffset() + possible.getLength());
- if (rootRegion != null && possRegion != null) {
- int rootStart = rootRegion.getStartOffset();
- int rootEnd = rootRegion2 != null ? rootRegion2.getEndOffset() : getDocument().getLength();
- int possStart = possRegion.getStartOffset();
- int possEnd = possRegion2 != null ? possRegion2.getEndOffset() : getDocument().getLength();
-
- if (rootStart <= possStart && rootEnd >= possEnd) {
- contains = true;
+ protected DirtyRegion getOuterRegion(DirtyRegion root, DirtyRegion possible) {
+ // first try simple region check if one region contains the other
+ DirtyRegion outer = super.getOuterRegion(root, possible);
+ if (outer == null) {
+ // now compare nodes
+ IStructuredModel sModel = getStructuredModelForRead(getDocument());
+ try {
+ if (sModel != null) {
+ IndexedRegion rootRegion = sModel.getIndexedRegion(root.getOffset());
+ IndexedRegion possRegion = sModel.getIndexedRegion(possible.getOffset());
+ if (rootRegion != null && possRegion != null) {
+ int rootStart = rootRegion.getStartOffset();
+ int possStart = possRegion.getStartOffset();
+ // first just check if rootregion starts before
+ // possregion
+ if (rootStart <= possStart) {
+ // check if possregion is inside rootregion
+ outer = _getOuterRegion(root, possible, sModel, rootStart, possStart);
+ }
+ else {
+ // otherwise if rootregion is inside possregion
+ outer = _getOuterRegion(possible, root, sModel, possStart, rootStart);
+ }
}
-
- if (DEBUG)
- System.out.println("checking if [" + rootStart + ":" + rootEnd + "] contains [" + possStart + ":" + possEnd + "] ... " + contains); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
}
+ finally {
+ if (sModel != null)
+ sModel.releaseFromRead();
+ }
}
- finally {
- if (sModel != null)
- sModel.releaseFromRead();
+ return outer;
+ }
+
+ /**
+ * Assumes that when this method is called, region1's node start offset >=
+ * region2's node start offset. Determines if region1 contains region2 or
+ * vice versa. Returns region1 if:
+ * <ul>
+ * <li>region1's node region == region2's node region</li>
+ * <li>region1's node region contains region2's node region</li>
+ * </ul>
+ * Returns region2 if:
+ * <ul>
+ * <li>region1's node region and region2's node region starts at same
+ * offset but region2's node region is longer</li>
+ * </ul>
+ * Returns null otherwise.
+ *
+ * @param region1
+ * @param region2
+ * @param sModel
+ * @param region1NodeStart
+ * @param region2NodeStart
+ * @return outer dirty region or null if none exists.
+ */
+ private DirtyRegion _getOuterRegion(DirtyRegion region1, DirtyRegion region2, IStructuredModel sModel, int region1NodeStart, int region2NodeStart) {
+ DirtyRegion outer = null;
+ int region1NodeEnd = -1;
+ int region2NodeEnd = -1;
+ // then check if region1's end appears after
+ // region2's end
+ IndexedRegion region1EndNode = sModel.getIndexedRegion(region1.getOffset() + region1.getLength());
+ if (region1EndNode == null) {
+ // if no end, just assume region spans all the
+ // way to the end so it includes other region
+ outer = region1;
}
- return contains;
+ else {
+ region1NodeEnd = region1EndNode.getEndOffset();
+ IndexedRegion region2EndNode = sModel.getIndexedRegion(region2.getOffset() + region2.getLength());
+ region2NodeEnd = region2EndNode != null ? region2EndNode.getEndOffset() : getDocument().getLength();
+ if (region1NodeEnd >= region2NodeEnd) {
+ // root contains or is equal to possible
+ outer = region1;
+ }
+ else if (region1NodeStart == region2NodeStart && region2NodeEnd >= region1NodeEnd) {
+ // possible contains root because they
+ // both start at same place but possible
+ // is longer
+ outer = region2;
+ }
+ }
+ if (DEBUG) {
+ if (outer != null)
+ System.out.println("checking if [" + region1NodeStart + ":" + region1NodeEnd + "] contains [" + region2NodeStart + ":" + region2NodeEnd + "] ... " + outer.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ else
+ System.out.println("checking if [" + region1NodeStart + ":" + region1NodeEnd + "] contains [" + region2NodeStart + ":" + region2NodeEnd + "] ... NO CONTAIN"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ }
+ return outer;
}
/**