@@ -13,15 +13,17 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer
1313 /// </summary>
1414 public class EditableText
1515 {
16+ private TextLines lines { get ; set ; }
17+
1618 /// <summary>
1719 /// The text that is available for editing.
1820 /// </summary>
19- public string Text { get ; private set ; }
21+ public string Text { get { return String . Join ( NewLine , lines ) ; } }
2022
2123 /// <summary>
2224 /// The lines in the Text.
2325 /// </summary>
24- public string [ ] Lines { get ; private set ; }
26+ public string [ ] Lines { get { return lines . ToArray ( ) ; } }
2527
2628 /// <summary>
2729 /// The new line character in the Text.
@@ -39,12 +41,11 @@ public EditableText(string text)
3941 throw new ArgumentNullException ( nameof ( text ) ) ;
4042 }
4143
42- this . Text = text ;
43- Lines = this . Text . GetLines ( ) . ToArray ( ) ;
44- NewLine = GetNewLineCharacters ( ) ;
44+ string [ ] lines ;
45+ NewLine = GetNewLineCharacters ( text , out lines ) ;
46+ this . lines = new TextLines ( lines ) ;
4547 }
4648
47- // TODO replace apply edit with an optimized version of this.
4849 /// <summary>
4950 /// Apply edits defined by a TextEdit object to Text.
5051 /// </summary>
@@ -55,24 +56,23 @@ public EditableText ApplyEdit(TextEdit textEdit)
5556 ValidateTextEdit ( textEdit ) ;
5657
5758 var editLines = textEdit . Lines ;
58- var Lines = new TextLines ( this . Lines ) ;
5959
6060 // Get the first fragment of the first line
6161 string firstLineFragment =
62- Lines [ textEdit . StartLineNumber - 1 ]
62+ lines [ textEdit . StartLineNumber - 1 ]
6363 . Substring ( 0 , textEdit . StartColumnNumber - 1 ) ;
6464
6565 // Get the last fragment of the last line
66- string endLine = Lines [ textEdit . EndLineNumber - 1 ] ;
66+ string endLine = lines [ textEdit . EndLineNumber - 1 ] ;
6767 string lastLineFragment =
6868 endLine . Substring (
6969 textEdit . EndColumnNumber - 1 ,
70- Lines [ textEdit . EndLineNumber - 1 ] . Length - textEdit . EndColumnNumber + 1 ) ;
70+ lines [ textEdit . EndLineNumber - 1 ] . Length - textEdit . EndColumnNumber + 1 ) ;
7171
7272 // Remove the old lines
7373 for ( int i = 0 ; i <= textEdit . EndLineNumber - textEdit . StartLineNumber ; i ++ )
7474 {
75- Lines . RemoveAt ( textEdit . StartLineNumber - 1 ) ;
75+ lines . RemoveAt ( textEdit . StartLineNumber - 1 ) ;
7676 }
7777
7878 // Build and insert the new lines
@@ -95,11 +95,11 @@ public EditableText ApplyEdit(TextEdit textEdit)
9595 finalLine = finalLine + lastLineFragment ;
9696 }
9797
98- Lines . Insert ( currentLineNumber - 1 , finalLine ) ;
98+ lines . Insert ( currentLineNumber - 1 , finalLine ) ;
9999 currentLineNumber ++ ;
100100 }
101101
102- return new EditableText ( String . Join ( NewLine , Lines ) ) ;
102+ return new EditableText ( String . Join ( NewLine , lines ) ) ;
103103 }
104104
105105 // TODO Add a method that takes multiple edits, checks if they are unique and applies them.
@@ -154,33 +154,35 @@ private int GetOffset(int lineNumber, int columnNumber)
154154 return offset + zeroBasedColumnNumber ;
155155 }
156156
157- private string GetNewLineCharacters ( )
157+ private static string GetNewLineCharacters ( string text , out string [ ] lines )
158158 {
159- if ( Lines . Length == 1 )
159+ int numNewLineChars = GetNumNewLineCharacters ( text , out lines ) ;
160+ if ( lines . Length == 1 )
160161 {
161162 return Environment . NewLine ;
162163 }
163164
164- return Text . Substring ( Lines [ 0 ] . Length , GetNumNewLineCharacters ( ) ) ;
165+ return text . Substring ( lines [ 0 ] . Length , numNewLineChars ) ;
165166 }
166167
167- private int GetNumNewLineCharacters ( )
168+ private static int GetNumNewLineCharacters ( string text , out string [ ] lines )
168169 {
169- if ( Lines . Length == 1 )
170+ lines = text . GetLines ( ) . ToArray ( ) ;
171+ if ( lines . Length == 1 )
170172 {
171173 return Environment . NewLine . Length ;
172174 }
173175
174- var charsInLines = Lines . Sum ( line => line . Length ) ;
175- var numCharDiff = Text . Length - charsInLines ;
176- int remainder = numCharDiff % ( Lines . Length - 1 ) ;
176+ var charsInLines = lines . Sum ( line => line . Length ) ;
177+ var numCharDiff = text . Length - charsInLines ;
178+ int remainder = numCharDiff % ( lines . Length - 1 ) ;
177179 if ( remainder != 0 )
178180 {
179181 // TODO localize
180- throw new ArgumentException ( "Cannot determine line endings as the text probably contain mixed line endings." , nameof ( Text ) ) ;
182+ throw new ArgumentException ( "Cannot determine line endings as the text probably contain mixed line endings." , nameof ( text ) ) ;
181183 }
182184
183- return numCharDiff / ( Lines . Length - 1 ) ;
185+ return numCharDiff / ( lines . Length - 1 ) ;
184186 }
185187
186188 private class TextLines : IList < String >
@@ -234,6 +236,7 @@ private LinkedListNode<String> GetNodeAt(int index)
234236 {
235237 if ( count == index )
236238 {
239+ SetLastAccessed ( index , node ) ;
237240 return node ;
238241 }
239242
@@ -260,10 +263,10 @@ private void GetClosestReference(
260263 var delta = index - lastAccessedIndex ;
261264 var deltaAbs = Math . Abs ( delta ) ;
262265
263- // lastAccessedIndex is closer to index than 0
266+ // lastAccessedIndex is closer to index than that to 0
264267 if ( IsLastAccessedValid ( ) && deltaAbs < index )
265268 {
266- // lastAccessedIndex is closer to index than Count - 1
269+ // lastAccessedIndex is closer to index than to ( Count - 1)
267270 if ( deltaAbs < ( Count - 1 - index ) )
268271 {
269272 refNode = lastAccessedNode ;
0 commit comments