[jbosstools-commits] JBoss Tools SVN: r42983 - in trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java: xpl and 1 other directory.

jbosstools-commits at lists.jboss.org jbosstools-commits at lists.jboss.org
Fri Aug 10 20:18:07 EDT 2012


Author: vrubezhny
Date: 2012-08-10 20:18:06 -0400 (Fri, 10 Aug 2012)
New Revision: 42983

Added:
   trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/xpl/
   trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/xpl/DirtyRegionProcessor.java
Modified:
   trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/JavaDirtyRegionProcessor.java
Log:
JBIDE-12418
Sometimes As-You-Type validation isn't invoked after a Java-String that contains EL is Copy-Pasted in Java editor 

Issue is fixed

Modified: trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/JavaDirtyRegionProcessor.java
===================================================================
--- trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/JavaDirtyRegionProcessor.java	2012-08-10 21:40:20 UTC (rev 42982)
+++ trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/JavaDirtyRegionProcessor.java	2012-08-11 00:18:06 UTC (rev 42983)
@@ -42,7 +42,7 @@
 import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.texteditor.IDocumentProvider;
 import org.eclipse.ui.texteditor.ITextEditor;
-import org.eclipse.wst.sse.ui.internal.reconcile.DirtyRegionProcessor;
+import org.jboss.tools.common.validation.java.xpl.DirtyRegionProcessor;
 import org.eclipse.wst.validation.internal.provisional.core.IMessage;
 import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;

Added: trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/xpl/DirtyRegionProcessor.java
===================================================================
--- trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/xpl/DirtyRegionProcessor.java	                        (rev 0)
+++ trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/xpl/DirtyRegionProcessor.java	2012-08-11 00:18:06 UTC (rev 42983)
@@ -0,0 +1,844 @@
+/*******************************************************************************
+  * Copyright (c) 2001, 2011 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.jboss.tools.common.validation.java.xpl;
+
+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.Platform;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.DocumentRewriteSessionEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IDocumentRewriteSessionListener;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.IReconcilerExtension;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.sse.ui.internal.reconcile.IConfigurableReconciler;
+
+/**
+ * This Job holds a queue of updates from the editor (DirtyRegions) to
+ * process. When a new request comes in, the current run is canceled, the new
+ * request is added to the queue, then the job is re-scheduled.
+ * 
+ * @author pavery
+ * 
+ * The class is copied from org.eclipse.jface.text.reconciler package and then 
+ * patch from https://bugs.eclipse.org/bugs/show_bug.cgi?id=384776 issue is applied on this class
+ * due to fix https://issues.jboss.org/browse/JBIDE-12418 issue.
+ */
+public class DirtyRegionProcessor implements IReconciler, IReconcilerExtension, IConfigurableReconciler {
+	class DocumentListener implements IDocumentListener {
+		public void documentAboutToBeChanged(DocumentEvent event) {
+			/*
+			 * if in rewrite session and already going to reprocess entire
+			 * document after rewrite session, do nothing
+			 */
+			if (isInRewriteSession() && fReprocessAfterRewrite)
+				return;
+			// save partition type (to see if it changes in documentChanged())
+			fLastPartitions = getPartitionRegions(event.getOffset(), event.getLength());
+		}
+
+		public void documentChanged(DocumentEvent event) {
+			/*
+			 * if in rewrite session and already going to reprocess entire
+			 * document after rewrite session, do nothing
+			 */
+			if (isInRewriteSession() && fReprocessAfterRewrite)
+				return;
+
+			if (partitionsChanged(event)) {
+				// pa_TODO
+				// this is a simple way to ensure old
+				// annotations are removed when partition changes
+
+				// it might be a performance hit though
+				setEntireDocumentDirty(getDocument());
+			}
+			else {
+				/*
+				 * bug 384776 - no wrong text may be included 
+				 */
+				DirtyRegion dr = null;
+				if (event.getLength() == 0) {
+					/*
+					 * It's an insert-- we use text length though so that the
+					 * new region gets validated...
+					 */
+					dr = createDirtyRegion(event.getOffset(), event.getText().length(), DirtyRegion.INSERT);
+				}
+				else {
+					if ("".equals(event.getText())) { //$NON-NLS-1$
+						// it's a delete-- we use text length=0
+						dr = createDirtyRegion(event.getOffset(), 0, DirtyRegion.REMOVE);
+					}
+					else {
+						// it's a replace-- we use text length though so that the new region gets validated...
+						dr = createDirtyRegion(event.getOffset(), event.getText().length(), DirtyRegion.INSERT);
+					}
+				}
+				if (isInRewriteSession()) {
+					/*
+					 * while in rewrite session, found a dirty region, so flag
+					 * that entire document needs to be reprocesed after
+					 * rewrite session
+					 */
+					if (!fReprocessAfterRewrite && (dr != null)) {
+						fReprocessAfterRewrite = true;
+					}
+				}
+				else {
+					processDirtyRegion(dr);
+				}
+			}
+		}
+
+		/**
+		 * Checks previous partitions from the span of the event w/ the new
+		 * partitions from the span of the event. If partitions changed,
+		 * return true, else return false
+		 * 
+		 * @param event
+		 * @return
+		 */
+		private boolean partitionsChanged(DocumentEvent event) {
+			boolean changed = false;
+			int length = event.getText().length(); // In any case we want partitions of the new text (even if its length is zero)
+
+			ITypedRegion[] newPartitions = getPartitionRegions(event.getOffset(), length);
+			if (fLastPartitions != null) {
+				if (fLastPartitions.length != newPartitions.length) {
+					changed = true;
+				}
+				else {
+					for (int i = 0; i < fLastPartitions.length; i++) {
+						if (!fLastPartitions[i].getType().equals(newPartitions[i].getType())) {
+							changed = true;
+							break;
+						}
+					}
+				}
+			}
+			return changed;
+		}
+	}
+
+	/**
+	 * Reconciles the entire document when the document in the viewer is
+	 * changed. This happens when the document is initially opened, as well as
+	 * after a save-as.
+	 * 
+	 * Also see processPostModelEvent(...) for similar behavior when document
+	 * for the model is changed.
+	 */
+	class TextInputListener implements ITextInputListener {
+		public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
+			// do nothing
+		}
+
+		public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+			handleInputDocumentChanged(oldInput, newInput);
+
+			startReconciling();
+		}
+	}
+
+	class DocumentRewriteSessionListener implements IDocumentRewriteSessionListener {
+		long time0 = 0;
+
+		public void documentRewriteSessionChanged(DocumentRewriteSessionEvent event) {
+			boolean oldValue = fInRewriteSession;
+			fInRewriteSession = event != null && event.getChangeType().equals(DocumentRewriteSessionEvent.SESSION_START);
+
+			if (event.getChangeType().equals(DocumentRewriteSessionEvent.SESSION_START)) {
+				if (DEBUG) {
+					time0 = System.currentTimeMillis();
+				}
+				// bug 235446 - source validation annotations lost after rewrite session
+				if (!getDirtyRegionQueue().isEmpty()) {
+					flushDirtyRegionQueue();
+					fReprocessAfterRewrite = true;	
+				} else {
+					fReprocessAfterRewrite = false;
+				}
+			}
+			else if (event.getChangeType().equals(DocumentRewriteSessionEvent.SESSION_STOP)) {
+				if (fInRewriteSession ^ oldValue && fDocument != null) {
+					if (DEBUG) {
+						Logger.log(Logger.INFO, "Rewrite session lasted " + (System.currentTimeMillis() - time0) + "ms");
+						time0 = System.currentTimeMillis();
+					}
+					if (fReprocessAfterRewrite) {
+						DirtyRegion entireDocument = createDirtyRegion(0, fDocument.getLength(), DirtyRegion.INSERT);
+						processDirtyRegion(entireDocument);
+					}
+					if (DEBUG) {
+						Logger.log(Logger.INFO, "Full document reprocess took " + (System.currentTimeMillis() - time0) + "ms");
+					}
+					fReprocessAfterRewrite = false;
+				}
+			}
+		}
+	}
+
+	/** debug flag */
+	protected static final boolean DEBUG;
+	private static final long UPDATE_DELAY = 500;
+
+	static {
+		String value = Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/reconcilerjob"); //$NON-NLS-1$
+		DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
+	}
+
+	private long fDelay;
+
+
+	/** local queue of dirty regions (created here) to be reconciled */
+	private List fDirtyRegionQueue = Collections.synchronizedList(new ArrayList());
+
+	/** document that this reconciler works on */
+	private IDocument fDocument = null;
+
+	private IDocumentListener fDocumentListener = new DocumentListener();
+	private IDocumentRewriteSessionListener fDocumentRewriteSessionListener = new DocumentRewriteSessionListener();
+
+	/**
+	 * set true after first install to prevent duplicate work done in the
+	 * install method (since install gets called multiple times)
+	 */
+	private boolean fIsInstalled = false;
+
+	/**
+	 * so we can tell if a partition changed after the last edit
+	 */
+	ITypedRegion[] fLastPartitions;
+
+	List fNonIncrementalStrategiesAlreadyProcessed = new ArrayList(1);
+
+	/**
+	 * The partitioning this reconciler uses.
+	 */
+	private String fPartitioning;
+
+	Map fReconcilingStrategies = null;
+
+	/** for initial reconcile when document is opened */
+	private TextInputListener fTextInputListener = null;
+	/** the text viewer */
+	private ITextViewer fViewer;
+	boolean fInRewriteSession = false;
+	/**
+	 * true if entire document needs to be reprocessed after rewrite session
+	 */
+	boolean fReprocessAfterRewrite = false;
+
+	/** The job should be reset because of document changes */
+	private boolean fReset = false;
+	private boolean fIsCanceled = false;
+	private boolean fHasReconciled = false;
+	private Object LOCK = new Object();
+
+	private BackgroundThread fThread;
+
+	/**
+	 * Creates a new StructuredRegionProcessor
+	 */
+	public DirtyRegionProcessor() {
+		// init reconciler stuff
+		setDelay(UPDATE_DELAY);
+		fReconcilingStrategies = new HashMap();
+	}
+
+	/**
+	 * Adds the given resource to the set of resources that need refreshing.
+	 * Synchronized in order to protect the collection during add.
+	 * 
+	 * @param resource
+	 */
+	private synchronized void addRequest(DirtyRegion newDirtyRegion) {
+		// NOTE: This method is called a lot so make sure it's fast
+		List dirtyRegionQueue = getDirtyRegionQueue();
+		synchronized (dirtyRegionQueue) {
+			for (Iterator it = dirtyRegionQueue.iterator(); it.hasNext();) {
+				// 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);
+		}
+	}
+
+	/**
+	 * Notifies subclasses that processing of multiple dirty regions has begun
+	 */
+	protected void beginProcessing() {
+		// do nothing by default
+	}
+
+	/**
+	 * @param dirtyRegion
+	 * @return
+	 */
+	protected ITypedRegion[] computePartitioning(DirtyRegion dirtyRegion) {
+		int drOffset = dirtyRegion.getOffset();
+		int drLength = dirtyRegion.getLength();
+
+		return computePartitioning(drOffset, drLength);
+	}
+
+	protected ITypedRegion[] computePartitioning(int drOffset, int drLength) {
+		ITypedRegion[] tr = new ITypedRegion[0];
+		IDocument doc = getDocument();
+		if (doc != null){
+			int docLength = doc.getLength();
+	
+			if (drOffset > docLength) {
+				drOffset = docLength;
+				drLength = 0;
+			}
+			else if (drOffset + drLength > docLength) {
+				drLength = docLength - drOffset;
+			}
+	
+			try {
+				// dirty region may span multiple partitions
+				tr = TextUtilities.computePartitioning(doc, getDocumentPartitioning(), drOffset, drLength, true);
+			}
+			catch (BadLocationException e) {
+				String info = "dr: [" + drOffset + ":" + drLength + "] doc: [" + docLength + "] "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				Logger.logException(info, e);
+				tr = new ITypedRegion[0];
+			}
+		}
+		return tr;
+	}
+
+	/**
+	 * 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
+	 */
+	private boolean isContained(DirtyRegion root, DirtyRegion possible) {
+		int rootStart = root.getOffset();
+		int rootEnd = rootStart + root.getLength();
+		int possStart = possible.getOffset();
+		int possEnd = possStart + possible.getLength();
+		if (rootStart <= possStart && rootEnd >= possEnd)
+			return true;
+		return false;
+	}
+
+	protected DirtyRegion createDirtyRegion(int offset, int length, String type) {
+		DirtyRegion durty = null;
+		IDocument doc = getDocument();
+
+		if (doc != null) {
+			// safety for BLE
+			int docLen = doc.getLength();
+			if (offset > docLen) {
+				offset = docLen;
+				length = 0;
+			}
+			else if (offset + length >= docLen)
+				length = docLen - offset;
+			try {
+				durty = new DirtyRegion(offset, length, type, doc.get(offset, length));
+			}
+			catch (BadLocationException e) {
+				String info = "dr: [" + offset + ":" + length + "] doc: [" + docLen + "] "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				Logger.logException(info, e);
+			}
+		}
+		return durty;
+	}
+
+	protected DirtyRegion createDirtyRegion(ITypedRegion tr, String type) {
+		return createDirtyRegion(tr.getOffset(), tr.getLength(), type);
+	}
+
+	protected void flushDirtyRegionQueue() {
+		synchronized (fDirtyRegionQueue) {
+			fDirtyRegionQueue.clear();
+		}
+	}
+
+	/**
+	 * Notifies subclasses that processing of multiple dirty regions has
+	 * ended, for now
+	 */
+	protected void endProcessing() {
+		// do nothing by default
+	}
+
+	/**
+	 * Delay between processing of DirtyRegions.
+	 * 
+	 * @return
+	 */
+	long getDelay() {
+		return fDelay;
+	}
+
+	List getDirtyRegionQueue() {
+		return fDirtyRegionQueue;
+	}
+
+	/**
+	 * The IDocument on which this reconciler operates
+	 * 
+	 * @return
+	 */
+	protected IDocument getDocument() {
+		return fDocument;
+	}
+
+	public String getDocumentPartitioning() {
+		if (fPartitioning == null)
+			return IDocumentExtension3.DEFAULT_PARTITIONING;
+		return fPartitioning;
+	}
+
+	protected String[] getPartitions(int drOffset, int drLength) {
+
+		ITypedRegion[] regions = new ITypedRegion[0];
+		int docLength = getDocument().getLength();
+
+		if (drOffset > docLength) {
+			drOffset = docLength;
+			drLength = 0;
+		}
+		else if (drOffset + drLength > docLength) {
+			drLength = docLength - drOffset;
+		}
+
+		try {
+			regions = TextUtilities.computePartitioning(getDocument(), getDocumentPartitioning(), drOffset, drLength, true);
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+			regions = new ITypedRegion[0];
+		}
+		String[] partitions = new String[regions.length];
+		for (int i = 0; i < regions.length; i++)
+			partitions[i] = regions[i].getType();
+		return partitions;
+	}
+
+	ITypedRegion[] getPartitionRegions(int drOffset, int drLength) {
+		ITypedRegion[] regions = new ITypedRegion[0];
+		int docLength = getDocument().getLength();
+
+		if (drOffset > docLength) {
+			drOffset = docLength;
+			drLength = 0;
+		}
+		else if (drOffset + drLength > docLength) {
+			drLength = docLength - drOffset;
+		}
+
+		try {
+			regions = TextUtilities.computePartitioning(getDocument(), getDocumentPartitioning(), drOffset, drLength, true);
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+			regions = new ITypedRegion[0];
+		}
+		return regions;
+	}
+		
+		
+	/**
+	 * Returns the reconciling strategy registered with the reconciler for the
+	 * specified partition type.
+	 * 
+	 * @param partitionType
+	 *            the partition type for which to determine the reconciling
+	 *            strategy
+	 * 
+	 * @return the reconciling strategy registered for the given partition
+	 *         type, or <code>null</code> if there is no such strategy
+	 * 
+	 * @see org.eclipse.jface.text.reconciler.IReconciler#getReconcilingStrategy(java.lang.String)
+	 */
+	public IReconcilingStrategy getReconcilingStrategy(String partitionType) {
+		if (partitionType == null)
+			return null;
+		return (IReconcilingStrategy) fReconcilingStrategies.get(partitionType);
+	}
+
+	/**
+	 * This method also synchronized because it accesses the fRequests queue
+	 * 
+	 * @return an array of the currently requested Nodes to refresh
+	 */
+	private synchronized DirtyRegion[] getRequests() {
+		synchronized (fDirtyRegionQueue) {
+			DirtyRegion[] toRefresh = (DirtyRegion[]) fDirtyRegionQueue.toArray(new DirtyRegion[fDirtyRegionQueue.size()]);
+			flushDirtyRegionQueue();
+			return toRefresh;
+		}
+	}
+
+	/**
+	 * Returns the text viewer this reconciler is installed on.
+	 * 
+	 * @return the text viewer this reconciler is installed on
+	 */
+	protected ITextViewer getTextViewer() {
+		return fViewer;
+	}
+
+	/**
+	 * 
+	 * @param oldInput
+	 * @param newInput
+	 */
+	void handleInputDocumentChanged(IDocument oldInput, IDocument newInput) {
+		// don't bother if reconciler not installed
+		if (isInstalled()) {
+			setDocument(newInput);
+		}
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.reconciler.IReconciler#install(ITextViewer)
+	 */
+	public void install(ITextViewer textViewer) {
+		// we might be called multiple times with the same viewe.r,
+		// maybe after being uninstalled as well, so track separately
+		if (!isInstalled()) {
+			fViewer = textViewer;
+			fTextInputListener = new TextInputListener();
+			textViewer.addTextInputListener(fTextInputListener);
+			setInstalled(true);
+		}
+		synchronized (this) {
+			if (fThread == null)
+				fThread = new BackgroundThread(getClass().getName());
+		}
+	}
+
+	/**
+	 * The viewer has been set on this Reconciler.
+	 * 
+	 * @return true if the viewer has been set on this Reconciler, false
+	 *         otherwise.
+	 */
+	public boolean isInstalled() {
+		return fIsInstalled;
+	}
+
+	boolean isInRewriteSession() {
+		return fInRewriteSession;
+	}
+
+	/**
+	 * Subclasses should implement for specific handling of dirty regions. The
+	 * method is invoked for each dirty region in the Job's queue.
+	 * 
+	 * @param dirtyRegion
+	 */
+	protected void process(DirtyRegion dirtyRegion) {
+		if (!isInstalled() || isInRewriteSession() || dirtyRegion == null || getDocument() == null || fIsCanceled) {
+			return;
+		}
+		/*
+		 * Break the dirty region into a sequence of partitions and find the
+		 * corresponding strategy to reconcile those partitions. If a strategy
+		 * implements INonIncrementalReconcilingStrategy, only call it once
+		 * regardless of the number and types of partitions.
+		 */
+		ITypedRegion[] partitions = computePartitioning(dirtyRegion);
+		for (int i = 0; i < partitions.length && !fIsCanceled; i++) {
+			IReconcilingStrategy strategy = getReconcilingStrategy(partitions[i].getType());
+			if (strategy != null) {
+				strategy.reconcile(partitions[i]);
+			}
+		}
+	}
+
+	/**
+	 * Invoke dirty region processing.
+	 * 
+	 * @param node
+	 */
+	public final void processDirtyRegion(DirtyRegion dr) {
+		if (dr == null || !isInstalled())
+			return;
+
+		addRequest(dr);
+		synchronized (LOCK) {
+			fReset = true;
+		}
+
+		if (DEBUG) {
+			System.out.println("added request for: [" + dr.getText() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+			System.out.println("queue size is now: " + getDirtyRegionQueue().size()); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Based on {@link org.eclipse.jface.text.reconciler.AbstractReconciler.BackgroundThread}
+	 *
+	 */
+	class BackgroundThread extends Thread {
+
+		public BackgroundThread(String name) {
+			super(name);
+			setPriority(Thread.MIN_PRIORITY);
+			setDaemon(true);
+		}
+
+		public void cancel() {
+			synchronized (fDirtyRegionQueue) {
+				fDirtyRegionQueue.notifyAll();
+			}
+		}
+
+		public void run() {
+			synchronized (fDirtyRegionQueue) {
+				try {
+					fDirtyRegionQueue.wait(getDelay());
+				} catch (InterruptedException e) {}
+			}
+
+			if (fIsCanceled)
+				return;
+
+			if (!fHasReconciled) {
+				initialReconcile();
+				fHasReconciled = true;
+			}
+
+			while (!fIsCanceled) {
+				synchronized (fDirtyRegionQueue) {
+					try {
+						fDirtyRegionQueue.wait(getDelay());
+					} catch (InterruptedException e) {}
+				}
+
+				if (fIsCanceled)
+					return;
+
+				synchronized (LOCK) {
+					if (fReset) {
+						fReset = false;
+						continue;
+					}
+				}
+
+				boolean processed = false;
+				try {
+					DirtyRegion[] toRefresh = getRequests();
+					if (toRefresh.length > 0) {
+						processed = true;
+						beginProcessing();
+					}
+	
+					for (int i = 0; i < toRefresh.length && fDocument != null; i++) {
+						if (fIsCanceled)
+							return;
+						process(toRefresh[i]);
+					}
+				}
+				finally {
+					if (processed)
+						endProcessing();
+				}
+				
+			}
+		}
+	}
+
+	public void setDelay(long delay) {
+		fDelay = delay;
+	}
+
+	public void setDocument(IDocument doc) {
+		if (fDocument != null) {
+			// unhook old document listener
+			fDocument.removeDocumentListener(fDocumentListener);
+			if (fDocument instanceof IDocumentExtension4) {
+				((IDocumentExtension4) fDocument).removeDocumentRewriteSessionListener(fDocumentRewriteSessionListener);
+			}
+		}
+
+		fDocument = doc;
+
+		if (fDocument != null) {
+			if (fDocument instanceof IDocumentExtension4) {
+				((IDocumentExtension4) fDocument).addDocumentRewriteSessionListener(fDocumentRewriteSessionListener);
+			}
+			// hook up new document listener
+			fDocument.addDocumentListener(fDocumentListener);
+
+			setEntireDocumentDirty(doc);
+		}
+	}
+
+	/**
+	 * This method is called before the initial reconciling of the document. 
+	 */
+	protected void initialReconcile() {
+	}
+
+	/**
+	 * Sets the document partitioning for this reconciler.
+	 * 
+	 * @param partitioning
+	 *            the document partitioning for this reconciler
+	 */
+	public void setDocumentPartitioning(String partitioning) {
+		fPartitioning = partitioning;
+	}
+
+	/**
+	 * Forces reconciling of the entire document.
+	 */
+	protected void forceReconciling() {
+		if (!fHasReconciled)
+			return;
+
+		setEntireDocumentDirty(getDocument());
+	}
+
+	/**
+	 * Basically means process the entire document.
+	 * 
+	 * @param document
+	 */
+	protected void setEntireDocumentDirty(IDocument document) {
+
+		// make the entire document dirty
+		// this also happens on a "save as"
+		if (document != null && isInstalled()) {
+
+			// since we're marking the entire doc dirty
+			flushDirtyRegionQueue();
+
+			/**
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=199053
+			 * 
+			 * Process the strategies for the last known-good partitions to
+			 * ensure all problem annotations are cleared if needed.
+			 */
+			if (fLastPartitions != null && document.getLength() == 0) {
+				for (int i = 0; i < fLastPartitions.length; i++) {
+					IReconcilingStrategy strategy = getReconcilingStrategy(fLastPartitions[i].getType());
+					if (strategy != null) {
+						strategy.reconcile(fLastPartitions[i]);
+					}
+				}
+			}
+			else {
+				DirtyRegion entireDocument = createDirtyRegion(0, document.getLength(), DirtyRegion.INSERT);
+				processDirtyRegion(entireDocument);
+			}
+		}
+	}
+
+	/**
+	 * @param isInstalled
+	 *            The isInstalled to set.
+	 */
+	void setInstalled(boolean isInstalled) {
+		fIsInstalled = isInstalled;
+	}
+
+	public void setReconcilingStrategy(String partitionType, IReconcilingStrategy strategy) {
+		if (partitionType == null) {
+			throw new IllegalArgumentException();
+		}
+
+		if (strategy == null) {
+			fReconcilingStrategies.remove(partitionType);
+		}
+		else {
+			fReconcilingStrategies.put(partitionType, strategy);
+		}
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.reconciler.IReconciler#uninstall()
+	 */
+	public void uninstall() {
+		if (isInstalled()) {
+			// removes widget listener
+			getTextViewer().removeTextInputListener(fTextInputListener);
+			setInstalled(false);
+			fIsCanceled = true;
+			synchronized (this) {
+				BackgroundThread bt = fThread;
+				fThread= null;
+				bt.cancel();
+			}
+		}
+		synchronized (fDirtyRegionQueue) {
+			fDirtyRegionQueue.clear();
+		}
+		setDocument(null);
+	}
+
+	protected synchronized void startReconciling() {
+		if (fThread == null)
+			return;
+		if (!fThread.isAlive()) {
+			try {
+				fThread.start();
+			} catch (IllegalThreadStateException e) { }
+		}
+	}
+}


Property changes on: trunk/common/plugins/org.jboss.tools.common.validation/src/org/jboss/tools/common/validation/java/xpl/DirtyRegionProcessor.java
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + text/plain



More information about the jbosstools-commits mailing list