]> O.S.I.I.S - jp/crowedit.git/commitdiff
TextBuffer class
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 25 Feb 2025 10:18:05 +0000 (11:18 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 25 Feb 2025 10:18:05 +0000 (11:18 +0100)
14 files changed:
.gitignore
CrowEditBase/src/Compiler/SourceDocument.cs
CrowEditBase/src/Compiler/SyntaxNode.cs
CrowEditBase/src/Compiler/Tokenizer.cs
CrowEditBase/src/SourceEditor.cs
CrowEditBase/src/TextDocument.cs
CrowEditBase/ui/sourceEditor.itmp
plugins/CECrowPlugin/src/ImlDocument.cs
plugins/CECrowPlugin/src/Parsing/Styling/StyleTokenizer.cs
plugins/CEEbnfPlugin/src/Parsing/EbnfTokenizer.cs
plugins/CERoslynPlugin/src/CSDocument.cs
plugins/CERoslynPlugin/src/CSTokenizer.cs
plugins/CEXmlPlugin/src/Parsing/XmlDocument.cs
plugins/CEXmlPlugin/src/Parsing/XmlTokenizer.cs

index 78de650055006945b2245bc828959d3e61e5fc1d..3521011d81d5596a3e4376e556df5d40af306dcb 100644 (file)
@@ -1,5 +1,6 @@
 CrowDesignAssembly/
 netcoredbg/
+testfiles/
 #Autosave files
 *~
 
index 48bfd658122258cd6e57710af7b2925061641d5e..c2ffdb5c2f065658f201845b449501b61780e906 100644 (file)
@@ -111,8 +111,7 @@ namespace CrowEditBase
                        SyntaxNode changedNode = RootNode.FindNodeIncludingSpan (TextSpan.FromStartAndLength (change.Start, change.ChangedText.Length));
                        
                        
-                       tokens = tokenizer.Tokenize (Source);
-
+                       tokens = tokenizer.Tokenize (buffer.Span);
 
 
                        syntaxAnalyser.Process ();
@@ -193,7 +192,7 @@ namespace CrowEditBase
                protected bool previousTokHasFlag(TokenType flag) => previousToken.HasValue && previousToken.Value.Type.HasFlag(flag);
                void parse () {
                        Tokenizer tokenizer = CreateTokenizer ();
-                       tokens = tokenizer?.Tokenize (Source);
+                       tokens = tokenizer?.Tokenize (source);
                        SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
                        Stopwatch sw = Stopwatch.StartNew ();
                        syntaxAnalyser?.Process ();
index 4d28970f55044f6303667be275a7f324d6e2ae07..0d418649ed8d3707e84cf3ca0619154a2714b7c1 100644 (file)
@@ -21,11 +21,13 @@ namespace CrowEditBase
                public override SyntaxNode NextSiblingOrParentsNextSibling => null;
                public override void UnfoldToTheTop() {}
                public string GetTokenStringByIndex (int idx) =>
-                       idx >= 0 && idx < source.Tokens.Length ? source.Tokens[idx].AsString (source.Source) : null;
+                       idx >= 0 && idx < source.Tokens.Length ? Root.GetText(source.Tokens[idx].Span).ToString() : null;
                public Token GetTokenByIndex (int idx) =>
                        idx >= 0 && idx < source.Tokens.Length ? source.Tokens[idx] : default;
                public ReadOnlySpan<char> GetText(TextSpan span) =>
                        source.GetText(span);
+               public string GetTokenString(Token tok) =>
+                       source.GetText(tok.Span).ToString();
        }
        public class SyntaxNode : CrowEditComponent {
                internal SyntaxNode () {}
index 06c33cadb5f50418e8cb4c12519eb0bc1492721b..ee3f2d6383772299920d4cb9092292f33c2eb7b3 100644 (file)
@@ -18,12 +18,12 @@ namespace CrowEditBase
                protected int startOfTok;
 
                public Tokenizer  () {}
-               public abstract Token[] Tokenize (string source);
+               public abstract Token[] Tokenize (ReadOnlySpan<char> source);
                /// <summary>
                /// First method to call in tokenizers to init parsing variables
                /// </summary>
                /// <returns></returns>
-               protected virtual SpanCharReader initParsing (string source) {
+               protected virtual SpanCharReader initParsing (ReadOnlySpan<char> source) {
                        startOfTok = 0;
                        Toks = new List<Token>(100);
                        return new SpanCharReader(source);
index a1aac8a95700e4aa3d1233b7f5f6f2086a4968ab..7a77750e15db67d83cca11ed5d41be4b4b639b14 100644 (file)
@@ -254,7 +254,7 @@ namespace Crow
                        using (IContext gr = IFace.Backend.CreateContext (IFace.MainSurface)) {
                                gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
                                gr.SetFontSize (Font.Size);
-                               updateLocation (gr, ClientRectangle.Width, ref hoverLoc);
+                               updateLocation (gr, ref hoverLoc);
                        }
 #if DEBUG_NODES
                        if (Document is SourceDocument doc) {
@@ -605,7 +605,7 @@ namespace Crow
                                Foreground.SetAsSource (IFace, gr);
                                gr.Translate (-ScrollX, -ScrollY);
 
-                               ReadOnlySpan<char> sourceBytes = doc.Source.AsSpan();
+                               ReadOnlySpan<char> sourceBytes = doc.source;
                                Span<byte> bytes = stackalloc byte[128];
                                TextExtents extents;
                                int tokPtr = 0;
index a786dc5a014e3b51d373cd5a4dda990c7d5bf458..d64ce276f8a1b11853ff4e80fe651720b8181954 100644 (file)
@@ -9,37 +9,72 @@ using System.IO;
 using Crow;
 using Crow.Text;
 using static CrowEditBase.CrowEditBase;
+using System.Collections.Immutable;
+using System.Reflection.Metadata;
 
 namespace CrowEditBase
 {
+       public class TextBuffer {
+               static int bufferExpension = 100;
+               int lenght;
+               Memory<char> buffer;
+               ReadOnlyMemory<char> origBuffer;
+               public Span<char> Span => buffer.Span.Slice(0, lenght);
+               public bool IsEmpty => lenght == 0;
+               public bool IsDirty => origBuffer.Span.Equals(buffer.Span, StringComparison.Ordinal);
+               public void ResetDirtyState () {
+                       origBuffer = buffer.ToArray();
+               }
+               public TextBuffer(ReadOnlySpan<char> origText) {
+                       lenght = origText.Length;
+                       buffer = new char[lenght + bufferExpension];
+                       origText.CopyTo(buffer.Span);
+               }
+               public void Update (TextChange change) {
+                       ReadOnlySpan<char> orig = buffer.Span;
+                       char[] newBuff = null;
+                       Span<char> tmp;
+                       if (buffer.Length < lenght + change.CharDiff) {
+                               newBuff = new char[lenght + change.CharDiff + bufferExpension];
+                               tmp = newBuff;
+                               orig.Slice(0, change.Start).CopyTo(tmp);
+                               if (change.CharDiff == 0)
+                                       orig.Slice(change.End, lenght - change.End).CopyTo(tmp.Slice(change.End));
+                       } else
+                               tmp = buffer.Span;
+                       
+                       if (change.CharDiff != 0)
+                               orig.Slice(change.End, lenght - change.End).CopyTo(tmp.Slice(change.End2));
+                       if (!string.IsNullOrEmpty (change.ChangedText))
+                               change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start));
+                       
+                       if (newBuff != null)
+                               buffer = newBuff;
+                       lenght += change.CharDiff;
+               }               
+       }
        public class TextDocument : Document {
                public TextDocument (string fullPath, string editorPath = "default")
                        : base (fullPath, editorPath) {
                        reloadFromFile ();
                }
 
-               string source, origSource;
+               protected TextBuffer buffer;
+               public ReadOnlySpan<char> source => buffer.Span;
+
                System.Text.Encoding encoding = System.Text.Encoding.UTF8;
                protected bool mixedLineBreak = false;
                protected string lineBreak = null;
 
-               public string Source {
-                       get => source;
-                       set {
-                               if (source == value)
-                                       return;
-                               source = value;
 
-                               getLines();
+                               
+
+//                             NotifyValueChanged ("IsDirty", IsDirty);
+//                             CMDSave.CanExecute = IsDirty;
 
-                               NotifyValueChanged (source);
-                               NotifyValueChanged ("IsDirty", IsDirty);
-                               CMDSave.CanExecute = IsDirty;
-                       }
-               }
                protected LineCollection lines;
 
-               public override bool IsDirty => origSource != source;
+               public override bool IsDirty => buffer.IsDirty;
                                /// dictionnary of object per document client, when not null, client must reload content of document.
                Dictionary<object, List<TextChange>> registeredClients = new Dictionary<object, List<TextChange>>();
                public override bool TryGetState<T>(object client, out T state) {
@@ -85,9 +120,9 @@ namespace CrowEditBase
                protected override void writeToDisk () {
                        using (Stream s = new FileStream(FullPath, FileMode.Create)) {
                                using (StreamWriter sw = new StreamWriter (s, encoding))
-                                       sw.Write (source);
+                                       sw.Write (buffer.Span);
                        }
-                       origSource = source;
+                       buffer.ResetDirtyState();
                        NotifyValueChanged ("IsDirty", IsDirty);
                        CMDSave.CanExecute = IsDirty;
                }
@@ -95,14 +130,14 @@ namespace CrowEditBase
                {
                        using (Stream s = new FileStream (FullPath, FileMode.Open)) {
                                using (StreamReader sr = new StreamReader (s)) {
-                                       Source = origSource = sr.ReadToEnd ();
+                                       buffer = new TextBuffer(sr.ReadToEnd ());
                                        encoding = sr.CurrentEncoding;
                                }
                        }
                }
                protected override void initNewFile()
                {
-                       Source = origSource = "";
+                       buffer = new TextBuffer("");
                }
                protected override void reloadFromFile () {
                        editorRWLock.EnterWriteLock ();
@@ -178,14 +213,7 @@ namespace CrowEditBase
                protected bool disableTextChangedEvent = false;
                protected virtual void apply (TextChange change) {
 
-                       Span<char> tmp = stackalloc char[source.Length + (change.ChangedText.Length - change.Length)];
-                       ReadOnlySpan<char> src = source.AsSpan ();
-                       src.Slice (0, change.Start).CopyTo (tmp);
-                       if (!string.IsNullOrEmpty (change.ChangedText))
-                               change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start));
-                       src.Slice (change.End).CopyTo (tmp.Slice (change.Start + change.ChangedText.Length));
-                       source = tmp.ToString ();
-
+                       buffer.Update(change);
                        lines.Update (change);
 
                        NotifyValueChanged ("IsDirty", IsDirty);
@@ -215,7 +243,7 @@ namespace CrowEditBase
                        else
                                lines.Clear ();
 
-                       if (string.IsNullOrEmpty (source))
+                       if (buffer.IsEmpty)
                                lines.Add (new TextLine (0, 0, 0));
                        else
                                lines.Update (source);
@@ -274,6 +302,8 @@ namespace CrowEditBase
                }
                public int LinesCount {
                        get {
+                               if (lines == null)
+                                       getLines();
                                editorRWLock.EnterReadLock ();
                                try {
                                        return lines.Count;
@@ -311,7 +341,7 @@ namespace CrowEditBase
                public ReadOnlySpan<char> GetText (TextSpan span) {
                        editorRWLock.EnterReadLock ();
                        try {
-                               return source.AsSpan (span.Start, span.Length);
+                               return source.Slice (span.Start, span.Length);
                        } finally {
                                editorRWLock.ExitReadLock();
                        }
index 321014a9b19522bc5bf20278e25f99dc49669357..ffeb398a70a2463cd861ea462d337022a28138cf 100644 (file)
@@ -1,42 +1,42 @@
 <?xml version="1.0"?>
 <ListItem IsVisible="{IsSelected}" IsSelected="{²IsSelected}" Selected="{/tb.HasFocus='true'}">
        <VerticalStack Spacing="0">
-               <HorizontalStack Spacing="0" Background="White">
-                       <SourceEditor Name="tb"  Font="mono, 14" Margin='0' CurrentNode="{CurrentNode}"
-                                       Document="{}" TextChanged="onTextChanged" />
-                       <ScrollBar Value="{²../tb.ScrollY}"
-                                       LargeIncrement="{../tb.PageHeight}" SmallIncrement="1"
-                                       CursorRatio="{../tb.ChildHeightRatio}" Maximum="{../tb.MaxScrollY}" />
-               </HorizontalStack>
-               <ScrollBar Style="HScrollBar" Value="{²../tb.ScrollX}"
-                               LargeIncrement="{../tb.PageWidth}" SmallIncrement="1"
-                               CursorRatio="{../tb.ChildWidthRatio}" Maximum="{../tb.MaxScrollX}" />
+                       <HorizontalStack Spacing="0" Background="White">
+                               <SourceEditor Name="tb"  Font="mono, 14" Margin='0' CurrentNode="{CurrentNode}"
+                                               Document="{}" TextChanged="onTextChanged" />
+                               <ScrollBar Value="{²../tb.ScrollY}"
+                                               LargeIncrement="{../tb.PageHeight}" SmallIncrement="1"
+                                               CursorRatio="{../tb.ChildHeightRatio}" Maximum="{../tb.MaxScrollY}" />
+                       </HorizontalStack>
+                       <ScrollBar Style="HScrollBar" Value="{²../tb.ScrollX}"
+                                       LargeIncrement="{../tb.PageWidth}" SmallIncrement="1"
+                                       CursorRatio="{../tb.ChildWidthRatio}" Maximum="{../tb.MaxScrollX}" />
+                       <HorizontalStack Height="Fit" Spacing='3'>
+                               <Widget Width="Stretched"/>
+                               <Label Text="TokType" Foreground="Grey"/>
+                               <Label Text="{CurrentTokenType}" Margin="3"/>
+                               <Label Text="Tok" Foreground="Grey"/>
+                               <Label Text="{CurrentTokenString}" Margin="3"/>
+                               <Label Text="Node" Foreground="Grey"/>
+                               <Label Text="{CurrentNode}" Margin="3"/>
+                               <Label Text="MouseY:" Foreground="Grey"/>
+                               <Label Text="{../../tb.MouseY}" Margin="3"/>
+                               <Label Text="VisibleLines:" Foreground="Grey"/>
+                               <Label Text="{../../tb.VisibleLines}" Margin="3"/>
+                               <Label Text="ScrollX:" Foreground="Grey"/>
+                               <Label Text="{../../tb.ScrollX}" Margin="3"/>
+                               <Label Text="ScrollY:" Foreground="Grey"/>
+                               <Label Text="{../../tb.ScrollY}" Margin="3"/>
+                               <Label Text="ScrollLine:" Foreground="Grey"/>
+                               <Label Text="{../../tb.ScrollLine}" Margin="3"/>
+                               <Label Text="HoverLine:" Foreground="Grey"/>
+                               <Label Text="{../../tb.HoverLine}" Margin="3"/>
+                               <Label Text="Line:" Foreground="Grey"/>
+                               <Label Text="{../../tb.CurrentLine}" Margin="3"/>
+                               <Label Text="Col:" Foreground="Grey"/>
+                               <Label Text="{../../tb.TabulatedColumn}" Margin="3"/>
+                       </HorizontalStack>
                <Splitter/>
-               <ListBox Data='{Exceptions}' Height='10%' Width='Stretched'/>
-               <HorizontalStack Height="Fit" Spacing='3'>
-                       <Widget Width="Stretched"/>
-                       <Label Text="TokType" Foreground="Grey"/>
-                       <Label Text="{CurrentTokenType}" Margin="3"/>
-                       <Label Text="Tok" Foreground="Grey"/>
-                       <Label Text="{CurrentTokenString}" Margin="3"/>
-                       <Label Text="Node" Foreground="Grey"/>
-                       <Label Text="{CurrentNode}" Margin="3"/>
-                       <Label Text="MouseY:" Foreground="Grey"/>
-                       <Label Text="{../../tb.MouseY}" Margin="3"/>
-                       <Label Text="VisibleLines:" Foreground="Grey"/>
-                       <Label Text="{../../tb.VisibleLines}" Margin="3"/>
-                       <Label Text="ScrollX:" Foreground="Grey"/>
-                       <Label Text="{../../tb.ScrollX}" Margin="3"/>
-                       <Label Text="ScrollY:" Foreground="Grey"/>
-                       <Label Text="{../../tb.ScrollY}" Margin="3"/>
-                       <Label Text="ScrollLine:" Foreground="Grey"/>
-                       <Label Text="{../../tb.ScrollLine}" Margin="3"/>
-                       <Label Text="HoverLine:" Foreground="Grey"/>
-                       <Label Text="{../../tb.HoverLine}" Margin="3"/>
-                       <Label Text="Line:" Foreground="Grey"/>
-                       <Label Text="{../../tb.CurrentLine}" Margin="3"/>
-                       <Label Text="Col:" Foreground="Grey"/>
-                       <Label Text="{../../tb.TabulatedColumn}" Margin="3"/>
-               </HorizontalStack>
+               <ListBox Data='{Exceptions}' Height='100' Width='Stretched'/>
        </VerticalStack>
 </ListItem>
index fad6b30f0cc0e3197da77dd7af7c76361f38e94a..9d4ddc3a67c1accda710f11e2a379bef65686aaa 100644 (file)
@@ -72,7 +72,7 @@ namespace CECrowPlugin
                        if (tok.GetTokenType() == XmlTokenType.ElementOpen)
                                return new List<string> (allWidgetNames);
                        if (tok.GetTokenType() == XmlTokenType.ElementName)
-                               return allWidgetNames.Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+                               return allWidgetNames.Where (s => s.StartsWith (RootNode.Root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
                        if ((tok.Type.HasFlag(TokenType.WhiteSpace) || previousTokHasFlag(TokenType.WhiteSpace)) &&
                                                tryCast(CurrentNode, out ElementTagSyntax ets)) {
                                if (ets.name.HasValue)
@@ -85,7 +85,7 @@ namespace CECrowPlugin
                                        if (!string.IsNullOrEmpty (eltTag.Name)) {
                                                if (tok.GetTokenType() == XmlTokenType.AttributeName) {
                                                        return getAllCrowTypeMembers (eltTag.Name)
-                                                               .Where (s => s.Name.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+                                                               .Where (s => s.Name.StartsWith (RootNode.Root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
                                                } else if (!string.IsNullOrEmpty (attribNode.Name)) {
                                                        if (tok.GetTokenType() == XmlTokenType.AttributeValue) {
                                                                MemberInfo mi = getCrowTypeMember (
@@ -93,19 +93,19 @@ namespace CECrowPlugin
                                                                if (mi is PropertyInfo pi) {
                                                                        if (pi.Name == "Style")
                                                                                return App.Styling.Keys
-                                                                                       .Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+                                                                                       .Where (s => s.StartsWith (RootNode.Root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
                                                                        if (pi.PropertyType.IsEnum)
                                                                                return Enum.GetNames (pi.PropertyType)
-                                                                                       .Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+                                                                                       .Where (s => s.StartsWith (RootNode.Root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
                                                                        if (pi.PropertyType == typeof(bool))
                                                                                return  (new string[] {"true", "false"}).
-                                                                                       Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+                                                                                       Where (s => s.StartsWith (RootNode.Root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
                                                                        if (pi.PropertyType == typeof (Measure))
                                                                                return (new string[] {"Stretched", "Fit"}).
-                                                                                       Where (s => s.StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+                                                                                       Where (s => s.StartsWith (RootNode.Root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
                                                                        if (pi.PropertyType == typeof (Fill))
                                                                                return  EnumsNET.Enums.GetValues<Colors> ()
-                                                                                       .Where (s => s.ToString().StartsWith (tok.AsString (Source), StringComparison.OrdinalIgnoreCase)).ToList ();
+                                                                                       .Where (s => s.ToString().StartsWith (RootNode.Root.GetTokenString(tok), StringComparison.OrdinalIgnoreCase)).ToList ();
                                                                }
                                                        } else if (tok.GetTokenType() == XmlTokenType.AttributeValueOpen) {
                                                                MemberInfo mi = getCrowTypeMember (
index 823bb865ff9e2d18bf46b8c1a82b355ce408509b..9275dd2cd3db971d71c3747a6f7aab06a9d354b0 100644 (file)
@@ -55,7 +55,7 @@ namespace CECrowPlugin.Style {
                        return false;
                }
 
-               public override Token[] Tokenize (string source) {
+               public override Token[] Tokenize (ReadOnlySpan<char> source) {
                        SpanCharReader reader = initParsing (source);
 
                        curState = States.classNames;
index f852d3b3bb2f3874214866495cb090de1b64def0..039dca5373b35f7e9800306e84c2198b121ffeab 100644 (file)
@@ -51,7 +51,7 @@ namespace CrowEdit.Ebnf
                public static bool IsValidHexDigit (char c) =>
                        char.IsDigit (c) || (c > 64 && c < 71) || (c > 96 && c < 103);
 
-               public override Token[] Tokenize (string source) {
+               public override Token[] Tokenize (ReadOnlySpan<char> source) {
                        SpanCharReader reader = new SpanCharReader(source);
 
                        startOfTok = 0;
index e9ebb21ef7e0bba2cf9cd0fba7e102e57623efea..efe786d484d073fe0d0fb1f7349b4179d836dbe5 100644 (file)
@@ -36,7 +36,7 @@ namespace CERoslynPlugin
                CSharpSyntaxTree tree;
                public CSDocument (string fullPath, string editorPath)  : base (fullPath, editorPath) {
 
-                       tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (Source, CSharpParseOptions.Default);
+                       tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (source.ToString(), CSharpParseOptions.Default);
                        var root = tree.GetRoot();
                        /*foreach (SyntaxKind v in Enum.GetValues<SyntaxKind>().OrderBy(k=>(uint)k)) {
                                Console.WriteLine($"{v,50} {(((uint)v) ).ToString("B16") } {(((uint)v) ).ToString("X4") }");
index 3a219a004c0983a14dc73f4fc373ed33b889442c..0644175687b69e56a0a58d0507def8de36266e5b 100644 (file)
@@ -68,9 +68,9 @@ namespace CERoslynPlugin
                        }
                }
 
-               public override Token[] Tokenize(string source)
+               public override Token[] Tokenize(ReadOnlySpan<char> source)
                {
-                       var tree = CSharpSyntaxTree.ParseText(source);
+                       var tree = CSharpSyntaxTree.ParseText(source.ToString());
                        CsharpSyntaxWalkerBridge bridge = new CsharpSyntaxWalkerBridge();
                        bridge.Visit(tree.GetRoot());
                        //SpanCharReader reader = new SpanCharReader(source);
index 09ef50961b57baa0cc78310ad71a94479392db83..0d1fa306354ac81cc87f385f4f9252bc4b829263 100644 (file)
@@ -33,7 +33,7 @@ namespace CrowEdit.Xml
                                CurrentNode is ElementEndTagSyntax eltEndTag && !eltEndTag.IsComplete) {
                                ElementSyntax es = eltEndTag.Parent as ElementSyntax;
                                if (es?.StartTag.name != null)
-                                       return new List<string> (new string[] {tokens[es.StartTag.name.Value].AsString(Source)});
+                                       return new List<string> (new string[] {es.StartTag.Name});
                        }                       
                        return null;
                }
@@ -84,7 +84,7 @@ namespace CrowEdit.Xml
                                } else {
                                        int offset = 1;
                                        if (!attrib.valueClose.HasValue) {
-                                               selectedSugg += tokens[attrib.valueClose.Value].AsString(Source);
+                                               selectedSugg += RootNode.Root.GetTokenStringByIndex(attrib.valueClose.Value);
                                                offset = 0;
                                        }
                                        if (tokType == XmlTokenType.AttributeValueOpen)
index 46f287ea6152e4aaa1bd937d9c322d98b894930e..c7fb88fb0a41f59076fcacd0f76df33cd9f7bddb 100644 (file)
@@ -64,7 +64,7 @@ namespace CrowEdit.Xml
                                reader.Read ();
                        }
                }
-               public override Token[] Tokenize (string source) {
+               public override Token[] Tokenize (ReadOnlySpan<char> source) {
                        SpanCharReader reader = initParsing (source);
 
                        int curObjectLevel = 0;