Browse Source

XML Parser: Cache renamed to TrackedSegmentCollection

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4688 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 16 years ago
parent
commit
9d83e3b0ab
  1. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  2. 6
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlContainer.cs
  3. 8
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlObject.cs
  4. 6
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlParser.cs
  5. 10
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagMatchingHeuristics.cs
  6. 10
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagReader.cs
  7. 19
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TrackedSegmentCollection.cs

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -326,7 +326,7 @@ @@ -326,7 +326,7 @@
<Compile Include="Xml\AXmlParser.cs" />
<Compile Include="Xml\AXmlTag.cs" />
<Compile Include="Xml\AXmlText.cs" />
<Compile Include="Xml\Cache.cs">
<Compile Include="Xml\TrackedSegmentCollection.cs">
<DependentUpon>AXmlParser.cs</DependentUpon>
</Compile>
<Compile Include="Xml\ExtensionMethods.cs" />

6
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlContainer.cs

@ -94,7 +94,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -94,7 +94,7 @@ namespace ICSharpCode.AvalonEdit.Xml
{
// Childs can be only added to newly parsed items
Assert(this.Parent == null, "I have to be new");
Assert(item.IsInCache, "Added item must be in cache");
Assert(item.IsCached, "Added item must be in cache");
// Do not set parent pointer
this.Children.InsertItemAt(this.Children.Count, item);
}
@ -198,8 +198,8 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -198,8 +198,8 @@ namespace ICSharpCode.AvalonEdit.Xml
Assert(child.Parent == this, "Inccorect parent reference");
}
Assert(myStartOffset <= child.StartOffset && child.EndOffset <= myEndOffset, "Child not within parent text range");
if (this.IsInCache)
Assert(child.IsInCache, "Child not in cache");
if (this.IsCached)
Assert(child.IsCached, "Child not in cache");
if (prevChild != null)
Assert(prevChild.EndOffset <= child.StartOffset, "Overlaping childs");
child.DebugCheckConsistency(checkParentPointers);

8
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/AXmlObject.cs

@ -162,7 +162,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -162,7 +162,7 @@ namespace ICSharpCode.AvalonEdit.Xml
/// <remarks> Initialized to 'this' </remarks>
internal AXmlObject LastUpdatedFrom { get; private set; }
internal bool IsInCache { get; set; }
internal bool IsCached { get; set; }
/// <summary> Is call to UpdateDataFrom is allowed? </summary>
internal bool CanUpdateDataFrom(AXmlObject source)
@ -170,7 +170,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -170,7 +170,7 @@ namespace ICSharpCode.AvalonEdit.Xml
return
this.GetType() == source.GetType() &&
this.StartOffset == source.StartOffset &&
(this.LastUpdatedFrom == source || !this.IsInCache);
(this.LastUpdatedFrom == source || !this.IsCached);
}
/// <summary> Copy all data from the 'source' to this object </summary>
@ -185,8 +185,8 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -185,8 +185,8 @@ namespace ICSharpCode.AvalonEdit.Xml
return false;
}
Assert(!this.IsInCache, "Can not update cached item");
Assert(source.IsInCache, "Must update from cache");
Assert(!this.IsCached, "Can not update cached item");
Assert(source.IsCached, "Must update from cache");
this.LastUpdatedFrom = source;
this.StartOffset = source.StartOffset;

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

@ -92,7 +92,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -92,7 +92,7 @@ namespace ICSharpCode.AvalonEdit.Xml
List<DocumentChangeEventArgs> changesSinceLastParse = new List<DocumentChangeEventArgs>();
internal Cache Cache { get; private set; }
internal TrackedSegmentCollection TrackedSegments { get; private set; }
/// <summary>
/// Generate syntax error when seeing enity reference other then the build-in ones
@ -105,7 +105,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -105,7 +105,7 @@ namespace ICSharpCode.AvalonEdit.Xml
this.input = input;
this.userDocument = new AXmlDocument() { Parser = this };
this.EntityReferenceIsError = true;
this.Cache = new Cache();
this.TrackedSegments = new TrackedSegmentCollection();
}
/// <summary>
@ -152,7 +152,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -152,7 +152,7 @@ namespace ICSharpCode.AvalonEdit.Xml
}
// Use chages to invalidate cache
this.Cache.UpdateOffsetsAndInvalidate(changesSinceLastParse);
this.TrackedSegments.UpdateOffsetsAndInvalidate(changesSinceLastParse);
changesSinceLastParse.Clear();
TagReader tagReader = new TagReader(this, input);

10
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagMatchingHeuristics.cs

@ -19,14 +19,14 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -19,14 +19,14 @@ namespace ICSharpCode.AvalonEdit.Xml
const int maxConfigurationCount = 10;
AXmlParser parser;
Cache cache;
TrackedSegmentCollection trackedSegments;
string input;
List<AXmlObject> tags;
public TagMatchingHeuristics(AXmlParser parser, string input, List<AXmlObject> tags)
{
this.parser = parser;
this.cache = parser.Cache;
this.trackedSegments = parser.TrackedSegments;
this.input = input;
this.tags = tags;
}
@ -56,7 +56,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -56,7 +56,7 @@ namespace ICSharpCode.AvalonEdit.Xml
}
AXmlParser.Log("Constructed {0}", doc);
cache.Add(doc, null);
trackedSegments.AddParsedObject(doc, null);
return doc;
}
@ -140,7 +140,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -140,7 +140,7 @@ namespace ICSharpCode.AvalonEdit.Xml
element.EndOffset = element.LastChild.EndOffset;
AXmlParser.Log("Constructed {0}", element);
cache.Add(element, null); // Need all elements in cache for offset tracking
trackedSegments.AddParsedObject(element, null); // Need all elements in cache for offset tracking
return element;
}
@ -179,7 +179,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -179,7 +179,7 @@ namespace ICSharpCode.AvalonEdit.Xml
"Expected '</{0}>'", topHalf.StartTag.Name);
AXmlParser.Log("Constructed {0}", topHalf);
cache.Add(topHalf, null);
trackedSegments.AddParsedObject(topHalf, null);
yield return topHalf;
for(int i = lastAccepted + 1; i < elem.Children.Count - 1; i++) {
yield return elem.Children[i];

10
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TagReader.cs

@ -16,13 +16,13 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -16,13 +16,13 @@ namespace ICSharpCode.AvalonEdit.Xml
class TagReader: TokenReader
{
AXmlParser parser;
Cache cache;
TrackedSegmentCollection trackedSegments;
string input;
public TagReader(AXmlParser parser, string input): base(input)
{
this.parser = parser;
this.cache = parser.Cache;
this.trackedSegments = parser.TrackedSegments;
this.input = input;
}
@ -33,7 +33,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -33,7 +33,7 @@ namespace ICSharpCode.AvalonEdit.Xml
bool TryReadFromCacheOrNew<T>(out T res, Predicate<T> condition) where T: AXmlObject, new()
{
T cached = cache.GetObject<T>(this.CurrentLocation, 0, condition);
T cached = trackedSegments.GetCachedObject<T>(this.CurrentLocation, 0, condition);
if (cached != null) {
Skip(cached.Length);
res = cached;
@ -47,7 +47,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -47,7 +47,7 @@ namespace ICSharpCode.AvalonEdit.Xml
void OnParsed(AXmlObject obj)
{
AXmlParser.Log("Parsed {0}", obj);
cache.Add(obj, this.MaxTouchedLocation > this.CurrentLocation ? (int?)this.MaxTouchedLocation : null);
trackedSegments.AddParsedObject(obj, this.MaxTouchedLocation > this.CurrentLocation ? (int?)this.MaxTouchedLocation : null);
}
/// <summary>
@ -451,7 +451,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -451,7 +451,7 @@ namespace ICSharpCode.AvalonEdit.Xml
// we hit that chache point. It is expensive so it is off for the first run
if (lookahead) {
// Note: Must fit entity
AXmlObject nextFragment = cache.GetObject<AXmlText>(this.CurrentLocation + maxEntityLength, lookAheadLenght - maxEntityLength, t => t.Type == type);
AXmlObject nextFragment = trackedSegments.GetCachedObject<AXmlText>(this.CurrentLocation + maxEntityLength, lookAheadLenght - maxEntityLength, t => t.Type == type);
if (nextFragment != null) {
fragmentEnd = Math.Min(nextFragment.StartOffset, this.InputLength);
AXmlParser.Log("Parsing only text ({0}-{1}) because later text was already processed", this.CurrentLocation, fragmentEnd);

19
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/Cache.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Xml/TrackedSegmentCollection.cs

@ -15,7 +15,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -15,7 +15,7 @@ namespace ICSharpCode.AvalonEdit.Xml
/// Holds all valid parsed items.
/// Also tracks their offsets as document changes.
/// </summary>
class Cache
class TrackedSegmentCollection
{
/// <summary> Previously parsed items as long as they are valid </summary>
TextSegmentCollection<AXmlObject> parsedItems = new TextSegmentCollection<AXmlObject>();
@ -51,18 +51,18 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -51,18 +51,18 @@ namespace ICSharpCode.AvalonEdit.Xml
// FindSegmentsContaining includes any segments touching
// so that conviniently takes care of the +1 byte
foreach(AXmlObject obj in parsedItems.FindSegmentsContaining(change.Offset)) {
Remove(obj, false);
InvalidateCache(obj, false);
}
foreach(TouchedRange range in touchedRanges.FindSegmentsContaining(change.Offset)) {
AXmlParser.Log("Found that {0} dependeds on ({1}-{2})", range.TouchedByObject, range.StartOffset, range.EndOffset);
Remove(range.TouchedByObject, true);
InvalidateCache(range.TouchedByObject, true);
touchedRanges.Remove(range);
}
}
}
/// <summary> Add object to cache, optionally adding extra memory tracking </summary>
public void Add(AXmlObject obj, int? maxTouchedLocation)
public void AddParsedObject(AXmlObject obj, int? maxTouchedLocation)
{
AXmlParser.Assert(obj.Length > 0 || obj is AXmlDocument, string.Format("Invalid object {0}. It has zero length.", obj));
if (obj is AXmlContainer) {
@ -76,7 +76,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -76,7 +76,7 @@ namespace ICSharpCode.AvalonEdit.Xml
foreach(SyntaxError syntaxError in obj.MySyntaxErrors) {
syntaxErrors.Add(syntaxError);
}
obj.IsInCache = true;
obj.IsCached = true;
if (maxTouchedLocation != null) {
// location is assumed to be read so the range ends at (location + 1)
// For example eg for "a_" it is (0-2)
@ -102,8 +102,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -102,8 +102,7 @@ namespace ICSharpCode.AvalonEdit.Xml
return parents;
}
/// <summary> Remove from cache </summary>
public void Remove(AXmlObject obj, bool includeParents)
void InvalidateCache(AXmlObject obj, bool includeParents)
{
if (includeParents) {
List<AXmlObject> parents = FindParents(obj);
@ -113,7 +112,7 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -113,7 +112,7 @@ namespace ICSharpCode.AvalonEdit.Xml
foreach(SyntaxError syntaxError in r.MySyntaxErrors) {
syntaxErrors.Remove(syntaxError);
}
r.IsInCache = false;
r.IsCached = false;
AXmlParser.Log("Removing cached item {0} (it is parent)", r);
}
}
@ -123,12 +122,12 @@ namespace ICSharpCode.AvalonEdit.Xml @@ -123,12 +122,12 @@ namespace ICSharpCode.AvalonEdit.Xml
foreach(SyntaxError syntaxError in obj.MySyntaxErrors) {
syntaxErrors.Remove(syntaxError);
}
obj.IsInCache = false;
obj.IsCached = false;
AXmlParser.Log("Removed cached item {0}", obj);
}
}
public T GetObject<T>(int offset, int lookaheadCount, Predicate<T> conditon) where T: AXmlObject, new()
public T GetCachedObject<T>(int offset, int lookaheadCount, Predicate<T> conditon) where T: AXmlObject, new()
{
AXmlObject obj = parsedItems.FindFirstSegmentWithStartAfter(offset);
while(obj != null && offset <= obj.StartOffset && obj.StartOffset <= offset + lookaheadCount) {
Loading…
Cancel
Save