Browse Source

XML Parser: ParseAndLock method in the XamlParser

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4719 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
0b8bf974ef
  1. 11
      samples/XmlDOM/Window1.xaml.cs
  2. 41
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs
  3. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/ParserTests.cs
  4. 44
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlParser.cs

11
samples/XmlDOM/Window1.xaml.cs

@ -37,6 +37,7 @@ namespace XmlDOM @@ -37,6 +37,7 @@ namespace XmlDOM
}
TextMarkerService markerService;
List<DocumentChangeEventArgs> changes = new List<DocumentChangeEventArgs>();
protected override void OnInitialized(EventArgs e)
{
@ -44,8 +45,11 @@ namespace XmlDOM @@ -44,8 +45,11 @@ namespace XmlDOM
editor.TextArea.TextView.MouseMove += new MouseEventHandler(editor_TextArea_TextView_MouseMove);
editor.Document.Changed += delegate { textDirty = true; };
parser = new AXmlParser(editor.Document);
editor.Document.Changed += delegate(object sender, DocumentChangeEventArgs e2) {
textDirty = true;
changes.Add(e2);
};
parser = new AXmlParser();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(0.5);
@ -75,7 +79,8 @@ namespace XmlDOM @@ -75,7 +79,8 @@ namespace XmlDOM
AXmlDocument doc;
parser.Lock.EnterWriteLock();
try {
doc = parser.Parse();
doc = parser.Parse(editor.Document.Text, changes);
changes.Clear();
} finally {
parser.Lock.ExitWriteLock();
}

41
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs

@ -5,13 +5,16 @@ @@ -5,13 +5,16 @@
// <version>$Revision: 2568 $</version>
// </file>
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.AvalonEdit.Document;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml;
using ICSharpCode.AvalonEdit.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.XamlBinding
{
@ -46,6 +49,42 @@ namespace ICSharpCode.XamlBinding @@ -46,6 +49,42 @@ namespace ICSharpCode.XamlBinding
{
return false;
}
AXmlParser axmlParser;
ICSharpCode.SharpDevelop.ITextBuffer lastParsedContent;
/// <summary>
/// Parse the given text and enter read lock.
/// No parsing is done if the text is older than seen before.
/// </summary>
public IDisposable ParseAndLock(ICSharpCode.SharpDevelop.ITextBuffer fileContent)
{
// Is fileContent newer?
if (lastParsedContent == null || fileContent.Version.CompareAge(lastParsedContent.Version) > 0) {
axmlParser.Lock.EnterWriteLock();
// Dobuble check, now that we are thread-safe
if (lastParsedContent == null) {
// First parse
axmlParser = new AXmlParser();
axmlParser.Parse(fileContent.Text, null);
lastParsedContent = fileContent;
} else if (fileContent.Version.CompareAge(lastParsedContent.Version) > 0) {
// Incremental parse
var changes = lastParsedContent.Version.GetChangesTo(fileContent.Version).
Select(c => new DocumentChangeEventArgs(c.Offset, c.RemovedText, c.InsertedText));
axmlParser.Parse(fileContent.Text, changes);
lastParsedContent = fileContent;
} else {
// fileContent is older - no need to parse
}
axmlParser.Lock.EnterReadLock();
axmlParser.Lock.ExitWriteLock();
} else {
// fileContent is older - no need to parse
axmlParser.Lock.EnterReadLock();
}
return new CallbackOnDispose(() => axmlParser.Lock.ExitReadLock());
}
public ICompilationUnit Parse(IProjectContent projectContent, string fileName, ICSharpCode.SharpDevelop.ITextBuffer fileContent)
{

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/XmlParser/ParserTests.cs

@ -154,7 +154,7 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests @@ -154,7 +154,7 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests
string content = testFile.Content;
Debug.WriteLine("Testing " + testFile.Name + "...");
AXmlParser parser = new AXmlParser(content);
AXmlParser parser = new AXmlParser();
bool usingDTD = content.Contains("<!DOCTYPE") && (content.Contains("<!ENTITY") || content.Contains(" SYSTEM "));
if (usingDTD)
@ -164,7 +164,7 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests @@ -164,7 +164,7 @@ namespace ICSharpCode.AvalonEdit.Xml.Tests
parser.Lock.EnterWriteLock();
try {
document = parser.Parse();
document = parser.Parse(content, null);
} finally {
parser.Lock.ExitWriteLock();
}

44
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlParser.cs

@ -88,13 +88,9 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -88,13 +88,9 @@ namespace ICSharpCode.AvalonEdit.Xml
/// </remarks>
public class AXmlParser
{
string input;
AXmlDocument userDocument;
TextDocument textDocument;
internal TrackedSegmentCollection TrackedSegments { get; private set; }
ChangeTrackingCheckpoint lastCheckpoint;
ReaderWriterLockSlim lockObject;
/// <summary>
/// Generate syntax error when seeing enity reference other then the build-in ones
@ -102,12 +98,11 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -102,12 +98,11 @@ namespace ICSharpCode.AvalonEdit.Xml
public bool UknonwEntityReferenceIsError { get; set; }
/// <summary> Create new parser </summary>
public AXmlParser(string input)
public AXmlParser()
{
this.input = input;
this.UknonwEntityReferenceIsError = true;
this.TrackedSegments = new TrackedSegmentCollection();
this.lockObject = new ReaderWriterLockSlim();
this.Lock = new ReaderWriterLockSlim();
this.userDocument = new AXmlDocument() { Parser = this };
this.userDocument.Document = this.userDocument;
@ -116,15 +111,6 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -116,15 +111,6 @@ namespace ICSharpCode.AvalonEdit.Xml
this.userDocument.IsCached = false;
}
/// <summary>
/// Create new parser, but do not parse the text yet.
/// </summary>
public AXmlParser(TextDocument textDocument)
: this(textDocument.Text)
{
this.textDocument = textDocument;
}
/// <summary> Throws exception if condition is false </summary>
internal static void Assert(bool condition, string message)
{
@ -147,23 +133,19 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -147,23 +133,19 @@ namespace ICSharpCode.AvalonEdit.Xml
System.Diagnostics.Debug.WriteLine(string.Format("XML: " + text, pars));
}
public AXmlDocument Parse()
/// <summary>
/// Incrementaly parse the given text.
/// You have to hold the write lock.
/// 'changesSinceLastParse' can be null on the first call.
/// </summary>
public AXmlDocument Parse(string input, IEnumerable<DocumentChangeEventArgs> changesSinceLastParse)
{
if (!Lock.IsWriteLockHeld)
throw new InvalidOperationException("Lock needed!");
if (textDocument != null) { // incremental parse
ChangeTrackingCheckpoint checkpoint;
input = textDocument.CreateSnapshot(out checkpoint).Text;
// Use changes to invalidate cache
if (lastCheckpoint != null) {
var changes = lastCheckpoint.GetChangesTo(checkpoint);
if (!changes.Any())
return userDocument;
this.TrackedSegments.UpdateOffsetsAndInvalidate(changes);
}
lastCheckpoint = checkpoint;
// Use changes to invalidate cache
if (changesSinceLastParse != null) {
this.TrackedSegments.UpdateOffsetsAndInvalidate(changesSinceLastParse);
}
TagReader tagReader = new TagReader(this, input);
@ -180,8 +162,6 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -180,8 +162,6 @@ namespace ICSharpCode.AvalonEdit.Xml
/// <summary>
/// Makes calls to Parse() thread-safe. Use Lock everywhere Parse() is called.
/// </summary>
public ReaderWriterLockSlim Lock {
get { return this.lockObject; }
}
public ReaderWriterLockSlim Lock { get; private set; }
}
}

Loading…
Cancel
Save