1
// Copyright (c) 2009-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections.Generic;
21
using System.Diagnostics;
22
using ICSharpCode.NRefactory.Editor;
24
namespace ICSharpCode.NRefactory.Xml
27
/// Encapsulates the state of the incremental tag soup parser.
29
public class IncrementalParserState
31
internal readonly int TextLength;
32
internal readonly ITextSourceVersion Version;
33
internal readonly InternalObject[] Objects;
35
internal IncrementalParserState(int textLength, ITextSourceVersion version, InternalObject[] objects)
37
this.TextLength = textLength;
38
this.Version = version;
39
this.Objects = objects;
42
internal List<UnchangedSegment> GetReuseMapTo(ITextSourceVersion newVersion)
44
ITextSourceVersion oldVersion = this.Version;
45
if (oldVersion == null || newVersion == null)
47
if (!oldVersion.BelongsToSameDocumentAs(newVersion))
49
List<UnchangedSegment> reuseMap = new List<UnchangedSegment>();
50
reuseMap.Add(new UnchangedSegment(0, 0, this.TextLength));
51
foreach (var change in oldVersion.GetChangesTo(newVersion)) {
52
bool needsSegmentRemoval = false;
53
for (int i = 0; i < reuseMap.Count; i++) {
54
UnchangedSegment segment = reuseMap[i];
55
if (segment.NewOffset + segment.Length <= change.Offset) {
56
// change is completely after this segment
59
if (change.Offset + change.RemovalLength <= segment.NewOffset) {
60
// change is completely before this segment
61
segment.NewOffset += change.InsertionLength - change.RemovalLength;
62
reuseMap[i] = segment;
65
// Change is overlapping segment.
66
// Split segment into two parts: the part before change, and the part after change.
67
var segmentBefore = new UnchangedSegment(segment.OldOffset, segment.NewOffset, change.Offset - segment.NewOffset);
68
Debug.Assert(segmentBefore.Length < segment.Length);
70
int lengthAtEnd = segment.NewOffset + segment.Length - (change.Offset + change.RemovalLength);
71
var segmentAfter = new UnchangedSegment(
72
segment.OldOffset + segment.Length - lengthAtEnd,
73
change.Offset + change.InsertionLength,
75
Debug.Assert(segmentAfter.Length < segment.Length);
76
Debug.Assert(segmentBefore.Length + segmentAfter.Length <= segment.Length);
77
Debug.Assert(segmentBefore.NewOffset + segmentBefore.Length <= segmentAfter.NewOffset);
78
Debug.Assert(segmentBefore.OldOffset + segmentBefore.Length <= segmentAfter.OldOffset);
79
if (segmentBefore.Length > 0 && segmentAfter.Length > 0) {
80
reuseMap[i] = segmentBefore;
81
reuseMap.Insert(++i, segmentAfter);
82
} else if (segmentBefore.Length > 0) {
83
reuseMap[i] = segmentBefore;
85
reuseMap[i] = segmentAfter;
86
if (segmentAfter.Length <= 0)
87
needsSegmentRemoval = true;
90
if (needsSegmentRemoval)
91
reuseMap.RemoveAll(s => s.Length <= 0);
97
struct UnchangedSegment
100
public int NewOffset;
103
public UnchangedSegment(int oldOffset, int newOffset, int length)
105
this.OldOffset = oldOffset;
106
this.NewOffset = newOffset;
107
this.Length = length;
110
public override string ToString()
112
return string.Format("[UnchangedSegment OldOffset={0}, NewOffset={1}, Length={2}]", OldOffset, NewOffset, Length);