diff --git a/AppInspector.Benchmarks/AppInspector.Benchmarks.csproj b/AppInspector.Benchmarks/AppInspector.Benchmarks.csproj
index fe532eaa..6379b919 100644
--- a/AppInspector.Benchmarks/AppInspector.Benchmarks.csproj
+++ b/AppInspector.Benchmarks/AppInspector.Benchmarks.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/AppInspector.CLI/AppInspector.CLI.csproj b/AppInspector.CLI/AppInspector.CLI.csproj
index ae65b0da..9616c3c3 100644
--- a/AppInspector.CLI/AppInspector.CLI.csproj
+++ b/AppInspector.CLI/AppInspector.CLI.csproj
@@ -67,7 +67,7 @@
-
+
diff --git a/AppInspector.RulesEngine/AppInspector.RulesEngine.csproj b/AppInspector.RulesEngine/AppInspector.RulesEngine.csproj
index a56c16e7..10a8061b 100644
--- a/AppInspector.RulesEngine/AppInspector.RulesEngine.csproj
+++ b/AppInspector.RulesEngine/AppInspector.RulesEngine.csproj
@@ -32,8 +32,8 @@
-
-
+
+
diff --git a/AppInspector.RulesEngine/RuleProcessor.cs b/AppInspector.RulesEngine/RuleProcessor.cs
index b8819673..7b3afa5e 100644
--- a/AppInspector.RulesEngine/RuleProcessor.cs
+++ b/AppInspector.RulesEngine/RuleProcessor.cs
@@ -8,6 +8,7 @@
using System.IO;
using System.Linq;
using System.Net;
+using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@@ -17,6 +18,8 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
+[assembly: InternalsVisibleTo("AppInspector.Tests")]
+
namespace Microsoft.ApplicationInspector.RulesEngine;
[ExcludeFromCodeCoverage]
@@ -531,7 +534,7 @@ private IEnumerable GetRulesByFileName(string fileName)
/// Simple wrapper but keeps calling code consistent
/// Do not html code result which is accomplished later before out put to report
///
- private string ExtractTextSample(string fileText, int index, int length)
+ internal string ExtractTextSample(string fileText, int index, int length)
{
if (index < 0 || length < 0)
{
@@ -554,7 +557,7 @@ private string ExtractTextSample(string fileText, int index, int length)
/// from the template
///
///
- private static string ExtractExcerpt(TextContainer text, Location start, Location end, Boundary matchBoundary, int context = 3)
+ internal static string ExtractExcerpt(TextContainer text, Location start, Location end, Boundary matchBoundary, int context = 3)
{
if (context == 0)
{
@@ -576,8 +579,10 @@ private static string ExtractExcerpt(TextContainer text, Location start, Locatio
// instead gather an appropriate number of characters
if (endIndex - startIndex - matchBoundary.Length > maxCharacterContext * 2)
{
+ // Limit start index to 0
startIndex = Math.Max(0, matchBoundary.Index - maxCharacterContext);
- endIndex = Math.Max(0, matchBoundary.Index + matchBoundary.Length + maxCharacterContext);
+ // Limit end index to length of overall content
+ endIndex = Math.Min(text.FullContent.Length, Math.Max(0, matchBoundary.Index + matchBoundary.Length + maxCharacterContext));
}
return text.FullContent[startIndex..endIndex];
diff --git a/AppInspector.Tests/RuleProcessor/ExtractSamplesTests.cs b/AppInspector.Tests/RuleProcessor/ExtractSamplesTests.cs
new file mode 100644
index 00000000..a8df387a
--- /dev/null
+++ b/AppInspector.Tests/RuleProcessor/ExtractSamplesTests.cs
@@ -0,0 +1,60 @@
+using System;
+using System.IO;
+using System.Linq;
+using Microsoft.ApplicationInspector.Logging;
+using Microsoft.ApplicationInspector.RulesEngine;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Serilog.Events;
+
+namespace AppInspector.Tests.RuleProcessor;
+
+[TestClass]
+public class ExtractSamplesTests
+{
+
+
+ private readonly ILoggerFactory _loggerFactory =
+ new LogOptions { ConsoleVerbosityLevel = LogEventLevel.Verbose }.GetLoggerFactory();
+
+ private ILogger _logger = new NullLogger();
+
+ [TestInitialize]
+ public void TestInit()
+ {
+ _logger = _loggerFactory.CreateLogger();
+ }
+
+ [TestCleanup]
+ public void TestCleanup()
+ {
+ }
+
+ const string shortTestString = "lorem ipsum dolor sit amet\nlorem ipsum dolor sit amet\nlorem ipsum dolor sit amet";
+ // Two lines 1000 long
+ const string longTestString = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
+ // Two lines 1000 long and a 10 character line at end
+ const string longTestStringShortThirdLine = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n1234567890";
+
+ // The string is short, so we get the whole thing (clamped on both sides)
+ [DataRow(shortTestString, 1,1,5,1,0,5,3,80)]
+ [DataRow(shortTestString, 1, 3, 5, 3, 54, 5, 3, 80)]
+ // These are 5 length at 0 index so we should only get context after (clamped on start)
+ [DataRow(longTestString, 1, 1, 5, 1, 0, 5, 3, 305)]
+ [DataRow(longTestString, 1, 1, 5, 1, 0, 5, 5, 505)]
+ // Third line is 10 character, context is set to 500 (specified as 5 lines then multiplied by 100) so 500 before, 10 after (clamped on end)
+ [DataRow(longTestStringShortThirdLine, 1, 3, 5, 3, 2000, 5, 5, 510)]
+
+ [DataTestMethod]
+ public void ExtractExcerptClampingTests(string testText, int StartCol, int StartLine, int EndCol, int EndLine, int Idx, int Length, int context, int expectedLength)
+ {
+ // Extract excerpt requires a text container
+ var tc = new TextContainer(testText, "csharp", new Microsoft.ApplicationInspector.RulesEngine.Languages(_loggerFactory), _loggerFactory);
+ var locStart = new Location() { Column = StartCol, Line = StartLine };
+ var locEnd = new Location() { Column = EndCol, Line = EndLine };
+ var boundary = new Boundary() { Index = Idx, Length = Length };
+ var result = Microsoft.ApplicationInspector.RulesEngine.RuleProcessor.ExtractExcerpt(tc, locStart, locEnd, boundary, context);
+ Assert.AreEqual(expectedLength, result.Length);
+ }
+}
\ No newline at end of file
diff --git a/AppInspector/AppInspector.Commands.csproj b/AppInspector/AppInspector.Commands.csproj
index f6402ba7..25d149cb 100644
--- a/AppInspector/AppInspector.Commands.csproj
+++ b/AppInspector/AppInspector.Commands.csproj
@@ -54,9 +54,9 @@
-
-
-
+
+
+