getting rid of IStructuredDocumentListener (using regular IDocument listener instead).
adding API for "partial" document validation (ISourceValidator).
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 d0db821..46c491f 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
@@ -250,11 +250,15 @@
 	 * @return
 	 */
 	protected String[] getPartitions(DirtyRegion dirtyRegion) {
-		ITypedRegion regions[] = null;
-        
         int drOffset = dirtyRegion.getOffset();
         int drLength = dirtyRegion.getLength();
-        int docLength = getDocument().getLength();
+        return getPartitions(drOffset, drLength);
+	}
+
+	protected String[] getPartitions(int drOffset, int drLength) {
+		
+		ITypedRegion[] regions = new ITypedRegion[0];
+		int docLength = getDocument().getLength();
         
         if(drOffset > docLength) {
             drOffset = docLength;
@@ -265,7 +269,7 @@
         }
             
 		try {
-			regions = TextUtilities.computePartitioning(getDocument(), getDocumentPartitioning(), dirtyRegion.getOffset(), dirtyRegion.getLength(), true);
+			regions = TextUtilities.computePartitioning(getDocument(), getDocumentPartitioning(), drOffset, drLength, true);
 		}
 		catch (BadLocationException e) {
 			Logger.logException(e);
@@ -276,7 +280,7 @@
 			partitions[i] = regions[i].getType();
 		return partitions;
 	}
-
+	
 	/**
 	 * contentType is actually partitionType
 	 * @see IReconciler#getReconcilingStrategy(String)
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredReconcileStep.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredReconcileStep.java
index cf2b3f1..5e98e91 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredReconcileStep.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredReconcileStep.java
@@ -90,7 +90,7 @@
 	 * @param sdRegion
 	 * @return
 	 */
-	private ITypedRegion getPartition(IStructuredDocumentRegion sdRegion) {
+	protected ITypedRegion getPartition(IStructuredDocumentRegion sdRegion) {
 		ITypedRegion tr = null;
 		if (!sdRegion.isDeleted())
 			tr = getPartition(sdRegion.getParentDocument(), sdRegion.getStartOffset());
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 40cf6e0..8e4ec75 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
@@ -17,12 +17,12 @@
 import java.util.Iterator;
 import java.util.List;
 
-import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
 import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
 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.IReconcilingStrategy;
 import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
@@ -32,29 +32,21 @@
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
 import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager;
-import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
-import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
-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.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.ui.internal.IReleasable;
 import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorBuilder;
 import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorMetaData;
 import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorStrategy;
 
 /**
- * Adds StructuredDocument and StructuredModel listeners. Adds Text viewer
+ * Adds IDocument and (Structured) ModelLifecycle listeners. Adds Text viewer
  * (dispose, input changed) listeners.
  * 
  * Implements a smarter "contains" method.
  * 
  * Adds default and validator strategies. Adds DirtyRegion processing logic.
  */
-public class StructuredRegionProcessor extends DirtyRegionProcessor implements IStructuredDocumentListener, IModelLifecycleListener {
+public class StructuredRegionProcessor extends DirtyRegionProcessor implements IDocumentListener, IModelLifecycleListener {
 
 	/**
 	 * Reconclies the entire document when the document in the viewer is
@@ -91,6 +83,9 @@
 	
 	private final String SSE_EDITOR_ID = "org.eclipse.wst.sse.ui"; //$NON-NLS-1$
 
+
+	private String[] fLastPartitions;
+
 	/**
 	 * @return Returns the fDefaultStrategy.
 	 */
@@ -126,6 +121,10 @@
 					if (sModel != null) {
 						contentTypeId = sModel.getContentTypeIdentifier();
 					}
+//					else {
+//						// some editors may be model-less (like JS)
+//						contentTypeId = getContentType(doc);
+//					}
 				} finally {
 					if (sModel != null)
 						sModel.releaseFromRead();
@@ -147,6 +146,28 @@
 		return fValidatorStrategy;
 	}
 
+//	private String getContentType(IDocument doc) {
+//		
+//		if(doc == null)
+//			return null;
+//		
+//		String contentTypeId = null;
+//		// no model, like w/ JS editor
+//		try {
+//			IContentDescription desc = Platform.getContentTypeManager().getDescriptionFor(new DocumentInputStream(doc), null, IContentDescription.ALL);
+//			if(desc != null) {
+//				IContentType ct  = desc.getContentType();
+//				if(ct != null) {
+//					contentTypeId = ct.getId();
+//				}
+//			}
+//		}
+//		catch (IOException e) {
+//			// just bail
+//		}
+//		return contentTypeId;
+//	}
+
 	/**
 	 * @param dirtyRegion
 	 */
@@ -264,18 +285,6 @@
 	}
 
 	/**
-	 * @param validatorStrategy
-	 *            The fValidatorStrategy to set.
-	 */
-	public void setValidatorStrategy(ValidatorStrategy validatorStrategy) {
-		fValidatorStrategy = validatorStrategy;
-		if (fValidatorStrategy != null) {
-			fValidatorStrategy.setDocument(getDocument());
-			fValidatorStrategy.setProgressMonitor(getLocalProgressMonitor());
-		}
-	}
-
-	/**
 	 * @see org.eclipse.wst.sse.ui.internal.reconcile.DirtyRegionProcessor#contains(org.eclipse.jface.text.reconciler.DirtyRegion,
 	 *      org.eclipse.jface.text.reconciler.DirtyRegion)
 	 */
@@ -287,19 +296,21 @@
 		boolean contains = false;
 		IStructuredModel sModel = getStructuredModelForRead(getDocument());
 		try {
-			IndexedRegion rootRegion = sModel.getIndexedRegion(root.getOffset());
-			IndexedRegion possRegion = sModel.getIndexedRegion(possible.getOffset());
-			if (rootRegion != null && possRegion != null) {
-				int rootStart = rootRegion.getStartOffset();
-				int rootEnd = rootRegion.getEndOffset();
-				int possStart = possRegion.getStartOffset();
-				int possEnd = possRegion.getEndOffset();
-
-				if (rootStart <= possStart && rootEnd >= possEnd)
-					contains = true;
-
-				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$
+			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 rootEnd = rootRegion.getEndOffset();
+					int possStart = possRegion.getStartOffset();
+					int possEnd = possRegion.getEndOffset();
+	
+					if (rootStart <= possStart && rootEnd >= possEnd)
+						contains = true;
+	
+					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 {
@@ -367,55 +378,6 @@
 		textViewer.addTextInputListener(fTextInputListener);
 	}
 
-	public void newModel(NewDocumentEvent structuredDocumentEvent) {
-		// happens on a revert
-		reconcilerDocumentChanged(structuredDocumentEvent.getDocument());
-	}
-
-	public void noChange(NoChangeEvent structuredDocumentEvent) {
-		// do nothing
-	}
-
-	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
-		if (DEBUG)
-			System.out.println("[trace reconciler] >StructuredRegionProcessor: *NODES REPLACED"); //$NON-NLS-1$
-
-		DirtyRegion dr = partitionChanged(structuredDocumentEvent) ? createDirtyRegion(0, getDocument().getLength(), DirtyRegion.INSERT) : createDirtyRegion(structuredDocumentEvent.getOffset(), structuredDocumentEvent.getLength(), DirtyRegion.INSERT);
-		processDirtyRegion(dr);
-	}
-
-	/**
-	 * Checks if the StructuredDocumentEvent involved a partition change. If
-	 * there's a partition change, we know we should run all strategies just
-	 * to be sure we cover the new regions and remove obsolete annotations.
-	 * 
-	 * A primitive check for now.
-	 * 
-	 * @param structuredDocumentEvent
-	 * @return
-	 */
-	private boolean partitionChanged(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
-		boolean changed = false;
-
-		IStructuredDocumentRegionList oldNodes = structuredDocumentEvent.getOldStructuredDocumentRegions();
-		IStructuredDocumentRegionList newNodes = structuredDocumentEvent.getNewStructuredDocumentRegions();
-
-		IStructuredDocumentRegion oldNode = (oldNodes.getLength() > 0) ? oldNode = oldNodes.item(0) : null;
-		IStructuredDocumentRegion newNode = (newNodes.getLength() > 0) ? newNodes.item(0) : null;
-
-		if (oldNode != null && newNode != null) {
-			try {
-				Object oldType = TextUtilities.getContentType(structuredDocumentEvent.getDocument(), getDocumentPartitioning(), oldNode.getStartOffset(), false);
-				Object newType = TextUtilities.getContentType(structuredDocumentEvent.getDocument(), getDocumentPartitioning(), newNode.getStartOffset(), false);
-				changed = !oldType.equals(newType);
-			}
-			catch (BadLocationException e) {
-				changed = true;
-			}
-		}
-		return changed;
-	}
-
 	/**
 	 * @see org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener#processPostModelEvent(org.eclipse.wst.sse.core.internal.model.ModelLifecycleEvent)
 	 */
@@ -482,33 +444,16 @@
 			hookUpModelLifecycleListener(newDocument);
 
 		// unhook old document listener
-		if (currentDoc != null && currentDoc instanceof IStructuredDocument)
-			((IStructuredDocument) currentDoc).removeDocumentChangedListener(this);
+		if (currentDoc != null)
+			currentDoc.removeDocumentListener(this);
 		// hook up new document listener
-		if (newDocument != null && newDocument instanceof IStructuredDocument)
-			((IStructuredDocument) newDocument).addDocumentChangedListener(this);
+		if (newDocument != null)
+			newDocument.addDocumentListener(this);
 
 		// sets document on all strategies
 		super.reconcilerDocumentChanged(newDocument);
 	}
 
-	public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
-		if (DEBUG)
-			System.out.println("[trace reconciler] >StructuredRegionProcessor: *REGION CHANGED: \r\n\r\n created dirty region from flat model event >> :" + structuredDocumentEvent.getOffset() + ":" + structuredDocumentEvent.getLength() + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
-		String dirtyRegionType = structuredDocumentEvent.getDeletedText().equals("") ? DirtyRegion.INSERT : DirtyRegion.REMOVE; //$NON-NLS-1$
-		DirtyRegion dr = createDirtyRegion(structuredDocumentEvent.getOffset(), structuredDocumentEvent.getLength(), dirtyRegionType);
-		processDirtyRegion(dr);
-	}
-
-	public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
-		if (DEBUG)
-			System.out.println("[trace reconciler] >StructuredRegionProcessor: *REGIONS REPLACED: \r\n\r\n created dirty region from flat model event >> :" + structuredDocumentEvent.getOffset() + ":" + structuredDocumentEvent.getLength() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
-		DirtyRegion dr = createDirtyRegion(structuredDocumentEvent.getOffset(), structuredDocumentEvent.getLength(), DirtyRegion.INSERT);
-		processDirtyRegion(dr);
-	}
-
 	protected void setEntireDocumentDirty(IDocument document) {
 
 		// make the entire document dirty
@@ -570,7 +515,81 @@
 					}
 				}
 			}
+			
+			IReconcilingStrategy defaultStrategy = getDefaultStrategy();
+			IReconcilingStrategy validatorStrategy = getValidatorStrategy();
+			
+			if(defaultStrategy != null) {
+				if(defaultStrategy instanceof IReleasable)
+					((IReleasable)defaultStrategy).release();
+			}
+			
+			if(validatorStrategy != null) {
+				if(validatorStrategy instanceof IReleasable)
+					((IReleasable)validatorStrategy).release();
+			}
 		}
 		super.uninstall();
 	}
+	
+	public void documentAboutToBeChanged(DocumentEvent event) {
+		// save partition type (to see if it changes)
+		fLastPartitions = getPartitions(event.getOffset(), event.getLength());			
+	}
+
+	public void documentChanged(DocumentEvent event) {
+		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 {
+			DirtyRegion dr = null;
+			if(event.getLength() == 0) {
+				// it's an insert
+				dr = createDirtyRegion(event.getOffset(), 0, DirtyRegion.INSERT);
+			}
+			else {
+				if(event.getText().equals("")) {
+					// it's a delete
+					dr =createDirtyRegion(event.getOffset(), event.getLength(), DirtyRegion.REMOVE);
+				}
+				else {
+					// it's a replace
+					dr = createDirtyRegion(event.getOffset(), event.getLength(), DirtyRegion.INSERT);	
+				}
+			}
+			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;
+		String[] newPartitions = getPartitions(event.getOffset(), event.getLength());
+		if(fLastPartitions != null) {
+			if(fLastPartitions.length != newPartitions.length) {
+				changed = true;
+			}
+			else {
+				for(int i=0; i<fLastPartitions.length; i++) {
+					if(!fLastPartitions[i].equals(newPartitions[i])) {
+						changed = true;
+						break;
+					}
+				}	
+			}
+		}
+		return changed;
+	}
 }
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ISourceValidator.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ISourceValidator.java
new file mode 100644
index 0000000..1e09976
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ISourceValidator.java
@@ -0,0 +1,42 @@
+package org.eclipse.wst.sse.ui.internal.reconcile.validator;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+
+/**
+ * Interface to allow for "partial document" as you type validation.
+ *
+ */
+public interface ISourceValidator {
+	
+	/**
+	 * As you type validation is getting "hooked up" to this IDocument.
+	 * This is the instance of IDocument that the validator should
+	 * operate on for each validate call.
+	 * 
+	 * @param document
+	 */
+	void connect(IDocument document);
+	
+	/**
+	 * The same IDocument passed in from the connect() method.
+	 * This indicates that as you type validation is "shutting down"
+	 * for this IDocument.
+	 * 
+	 * @param document
+	 */
+	void disconnect(IDocument document);
+	
+	/**
+	 * Like IValidator#validate(IValidationContext helper, IReporter reporter)
+	 * except passes the dirty region, so document validation can be better
+	 * optimized.
+	 * 
+	 * @param dirtyRegion
+	 * @param helper
+	 * @param reporter
+	 */
+	void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter);
+}
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ReconcileStepForValidator.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ReconcileStepForValidator.java
index a239ea1..70b91ad 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ReconcileStepForValidator.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ReconcileStepForValidator.java
@@ -21,14 +21,17 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.IRegion;
 import org.eclipse.jface.text.Position;
 import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilableModel;
 import org.eclipse.jface.text.reconciler.IReconcileResult;
 import org.eclipse.jface.text.reconciler.IReconcileStep;
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager;
 import org.eclipse.wst.sse.ui.internal.Logger;
+import org.eclipse.wst.sse.ui.internal.reconcile.DocumentAdapter;
 import org.eclipse.wst.sse.ui.internal.reconcile.ReconcileAnnotationKey;
 import org.eclipse.wst.sse.ui.internal.reconcile.StructuredReconcileStep;
 import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
@@ -185,7 +188,12 @@
 		IReconcileResult[] results = EMPTY_RECONCILE_RESULT_SET;
 		if (dirtyRegion != null) {
 			try {
-				results = validate();
+				if(fValidator instanceof ISourceValidator) {
+					results = validate(dirtyRegion, subRegion);
+				}
+				else {
+					results = validate();
+				}
 			}
 			catch (Exception ex) {
 				Logger.logException("EXEPTION IN RECONCILE STEP FOR VALIDATOR", ex); //$NON-NLS-1$
@@ -204,7 +212,7 @@
 			debugString.append(fValidator.getClass().toString());
 		return debugString.toString();
 	}
-
+	
 	protected IReconcileResult[] validate() {
 		IReconcileResult[] results = EMPTY_RECONCILE_RESULT_SET;
 
@@ -230,4 +238,58 @@
 		}
 		return results;
 	}
+	
+	public void setInputModel(IReconcilableModel inputModel) {
+		if(inputModel instanceof DocumentAdapter) {
+			IDocument document = ((DocumentAdapter)inputModel).getDocument();
+			if(document != null) {
+				if(fValidator instanceof ISourceValidator) {
+					// notify that document connecting
+					((ISourceValidator)fValidator).connect(document);
+				}
+			}
+		}
+		super.setInputModel(inputModel);
+	}
+	
+	public void release() {
+		if(fValidator instanceof ISourceValidator) {
+			IDocument document = getDocument();
+			if(document != null) {
+				// notify that document disconnecting
+				((ISourceValidator)fValidator).disconnect(document);
+			}
+		}
+		super.release();
+	}
+	
+	protected IReconcileResult[] validate(DirtyRegion dirtyRegion, IRegion subRegion) {
+ 		IReconcileResult[] results = EMPTY_RECONCILE_RESULT_SET;
+ 
+ 		IFile file = getFile();
+		try {
+			IProject project = null;
+			if (file != null)
+				project = file.getProject();
+ 
+			IncrementalHelper helper = getHelper(project);
+
+			if (file != null)
+				helper.setURI(file.getFullPath().toString());
+ 
+			if(fValidator instanceof ISourceValidator) {
+				IncrementalReporter reporter = getReporter();
+				((ISourceValidator)fValidator).validate(dirtyRegion, helper, reporter);
+				results = createAnnotations(reporter.getMessages());
+				reporter.removeAllMessages(fValidator);
+			}
+
+		} catch (Exception e) {
+			Logger.logException(e);
+ 		}
+ 		return results;
+ 	}
+	
+	
+	
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java
index c3966f5..1a8a396 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/validator/ValidatorStrategy.java
@@ -29,6 +29,7 @@
 import org.eclipse.jface.text.reconciler.IReconcileResult;
 import org.eclipse.jface.text.reconciler.IReconcileStep;
 import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.wst.sse.ui.internal.IReleasable;
 import org.eclipse.wst.sse.ui.internal.reconcile.AbstractStructuredTextReconcilingStrategy;
 import org.eclipse.wst.sse.ui.internal.reconcile.DocumentAdapter;
 import org.eclipse.wst.sse.ui.internal.reconcile.StructuredReconcileStep;
@@ -201,6 +202,17 @@
 		}
 	}
 	
+	public void release() {
+		super.release();
+		Iterator it = fVidToVStepMap.values().iterator();
+		IReconcileStep step = null;
+		while (it.hasNext()) {
+			step = (IReconcileStep) it.next();
+			if(step instanceof IReleasable)
+				((IReleasable)step).release();
+		}
+	}
+	
 	public boolean isTotalScope() {
 		return true;
 	}