diff --git a/Engine/EditableText.cs b/Engine/EditableText.cs
index 7aae0c28a..93f78d66a 100644
--- a/Engine/EditableText.cs
+++ b/Engine/EditableText.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Management.Automation.Language;
@@ -16,6 +17,11 @@ public class EditableText
{
private TextLines lines { get; set; }
+ ///
+ /// Return the number of lines in the text.
+ ///
+ public int LineCount => lines.Count;
+
///
/// The text that is available for editing.
///
@@ -24,7 +30,7 @@ public class EditableText
///
/// The lines in the Text.
///
- public string[] Lines { get { return lines.ToArray(); } }
+ public ReadOnlyCollection Lines => lines.ReadOnly();
///
/// The new line character in the Text.
@@ -118,8 +124,8 @@ public bool IsValidRange(Range range)
throw new ArgumentNullException(nameof(range));
}
- return range.Start.Line <= Lines.Length
- && range.End.Line <= Lines.Length
+ return range.Start.Line <= Lines.Count
+ && range.End.Line <= Lines.Count
&& range.Start.Column <= Lines[range.Start.Line - 1].Length
&& range.End.Column <= Lines[range.End.Line - 1].Length + 1;
}
diff --git a/Engine/ScriptAnalyzer.cs b/Engine/ScriptAnalyzer.cs
index 919ba8df0..5c3a6ec03 100644
--- a/Engine/ScriptAnalyzer.cs
+++ b/Engine/ScriptAnalyzer.cs
@@ -1557,7 +1557,6 @@ public EditableText Fix(EditableText text, Range range, out Range updatedRange)
throw new ArgumentNullException(nameof(text));
}
- // todo validate range
var isRangeNull = range == null;
if (!isRangeNull && !text.IsValidRange(range))
{
@@ -1569,7 +1568,7 @@ public EditableText Fix(EditableText text, Range range, out Range updatedRange)
}
range = isRangeNull ? null : SnapToEdges(text, range);
- var previousLineCount = text.Lines.Length;
+ var previousLineCount = text.LineCount;
var previousUnusedCorrections = 0;
do
{
@@ -1598,9 +1597,7 @@ public EditableText Fix(EditableText text, Range range, out Range updatedRange)
}
previousUnusedCorrections = unusedCorrections;
-
- // todo add a TextLines.NumLines property because accessing TextLines.Lines is expensive
- var lineCount = text.Lines.Length;
+ var lineCount = text.LineCount;
if (!isRangeNull && lineCount != previousLineCount)
{
range = new Range(
diff --git a/Engine/TextLines.cs b/Engine/TextLines.cs
index abbe9c9cb..722501303 100644
--- a/Engine/TextLines.cs
+++ b/Engine/TextLines.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
@@ -80,6 +81,15 @@ public string this[int index]
}
}
+ ///
+ /// Return a readonly collection of the current object.
+ ///
+ /// A readonly collection of the current object.
+ public ReadOnlyCollection ReadOnly()
+ {
+ return new ReadOnlyCollection(this);
+ }
+
///
/// Adds the given string to the end of the list.
///
diff --git a/Tests/Engine/EditableText.tests.ps1 b/Tests/Engine/EditableText.tests.ps1
index ce207a721..c6f888f08 100644
--- a/Tests/Engine/EditableText.tests.ps1
+++ b/Tests/Engine/EditableText.tests.ps1
@@ -104,5 +104,38 @@ function foo {
$result = $editableText.ApplyEdit($edit)
$result.ToString() | Should Be $expected
}
+
+ It "Should return a read-only collection of lines in the text" {
+ $def = @'
+function foo {
+ param(
+ [bool] $param1
+ )
+}
+'@
+ $text = New-Object `
+ -TypeName "Microsoft.Windows.PowerShell.ScriptAnalyzer.EditableText" `
+ -ArgumentList @($def)
+
+ {$text.Lines.Add("abc")} | Should Throw
+ }
+
+ It "Should return the correct number of lines in the text" {
+ $def = @'
+function foo
+{
+get-childitem
+$x=1+2
+$hashtable = @{
+property1 = "value"
+ anotherProperty = "another value"
+}
+}
+'@
+ $text = New-Object `
+ -TypeName "Microsoft.Windows.PowerShell.ScriptAnalyzer.EditableText" `
+ -ArgumentList @($def)
+ $text.LineCount | Should Be 9
+ }
}
}