Skip to content

Commit

Permalink
Add subscriptions to the check aggregator to enable multiple webviews
Browse files Browse the repository at this point in the history
  • Loading branch information
lyonsil committed Nov 21, 2024
1 parent 2ac8c93 commit 927677e
Show file tree
Hide file tree
Showing 24 changed files with 1,461 additions and 325 deletions.
36 changes: 26 additions & 10 deletions c-sharp-tests/Checks/CheckRunResultTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ namespace TestParanextDataProvider.Checks;

public class CheckRunResultTests
{
[TestCase("checkId", "projectId", "message", "GEN 1:1", 1, "GEN 1:2", 5, true)]
[TestCase("ABC", "projectId", "message", "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "ABC", "message", "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "projectId", "ABC", "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "projectId", "message", "GEN 1:2", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "projectId", "message", "GEN 1:1", 2, "GEN 1:2", 5, false)]
[TestCase("checkId", "projectId", "message", "GEN 1:1", 1, "GEN 1:3", 5, false)]
[TestCase("checkId", "projectId", "message", "GEN 1:1", 1, "GEN 1:2", 7, false)]
[TestCase("checkId", "resType", "projectId", "msg", false, "GEN 1:1", 1, "GEN 1:2", 5, true)]
[TestCase("ABC", "resType", "projectId", "msg", false, "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "ABC", "projectId", "msg", false, "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "resType", "ABC", "msg", false, "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "resType", "projectId", "ABC", false, "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "resType", "projectId", "msg", true, "GEN 1:1", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "resType", "projectId", "msg", false, "GEN 1:2", 1, "GEN 1:2", 5, false)]
[TestCase("checkId", "resType", "projectId", "msg", false, "GEN 1:1", 2, "GEN 1:2", 5, false)]
[TestCase("checkId", "resType", "projectId", "msg", false, "GEN 1:1", 1, "GEN 1:3", 5, false)]
[TestCase("checkId", "resType", "projectId", "msg", false, "GEN 1:1", 1, "GEN 1:2", 7, false)]
public void Equality_Objects_ComparedByValue(
string checkId2,
string checkResultType2,
string projectId2,
string message2,
bool isDenied2,
string verseRefStart2,
int offsetStart2,
string verseRefEnd2,
Expand All @@ -28,13 +32,25 @@ bool expectedResult
CheckLocation start1 = new(vrefStart1, 1);
VerseRef vrefEnd1 = new("GEN 1:2");
CheckLocation end1 = new(vrefEnd1, 5);
CheckRunResult checkRunResult1 = new("checkId", "projectId", "message", "", start1, end1);
CheckRunResult checkRunResult1 =
new("checkId", "resType", "projectId", "msg", "", false, vrefStart1, start1, end1);

VerseRef vrefStart2 = new(verseRefStart2);
CheckLocation start2 = new(vrefStart2, offsetStart2);
VerseRef vrefEnd2 = new(verseRefEnd2);
CheckLocation end2 = new(vrefEnd2, offsetEnd2);
CheckRunResult checkRunResult2 = new(checkId2, projectId2, message2, "", start2, end2);
CheckRunResult checkRunResult2 =
new(
checkId2,
checkResultType2,
projectId2,
message2,
"",
isDenied2,
vrefStart2,
start2,
end2
);

Assert.That(checkRunResult1 == checkRunResult2, Is.EqualTo(expectedResult));
Assert.That(checkRunResult1.Equals(checkRunResult2), Is.EqualTo(expectedResult));
Expand Down
97 changes: 73 additions & 24 deletions c-sharp/Checks/CheckResultsRecorder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ public void RecordError(
CheckRunResults.Add(
new CheckRunResult(
checkId,
messageId.InternalValue,
projectId,
message,
// ParatextData adds a space at the end sometimes that isn't in the text
token.Text.TrimEnd(),
false,
token.VerseRef,
// Actual offsets will be calculated below after results have been filtered
new CheckLocation(token.VerseRef, offset),
new CheckLocation(token.VerseRef, 0)
Expand All @@ -55,10 +58,13 @@ public void RecordError(
CheckRunResults.Add(
new CheckRunResult(
checkId,
messageId.InternalValue,
projectId,
message,
// ParatextData adds a space at the end sometimes that isn't in the text
text.TrimEnd(),
false,
vref,
// Actual offsets will be calculated below after results have been filtered
new CheckLocation(vref, selectionStart),
new CheckLocation(vref, 0)
Expand Down Expand Up @@ -87,42 +93,85 @@ public List<CheckRunResult> TrimResultsFromBook(int bookNum)
}

/// <summary>
/// Remove all results that are not within the given range
/// After a check has finished running, filter and complete filling in data on the results found.
/// This will:<br/>
/// 1. Remove all results that are not within the given ranges<br/>
/// 2. Lookup whether each check result was previously denied<br/>
/// 3. Calculate actual offsets for each result
/// </summary>
public void FilterResults(CheckInputRange range)
public void PostProcessResults(
CheckInputRange[]? ranges,
ErrorMessageDenials? denials,
UsfmBookIndexer? indexer
)
{
for (int i = CheckRunResults.Count - 1; i >= 0; i--)
{
var result = CheckRunResults[i];
var verseRef = result.Start.VerseRef;
if (!range.IsWithinRange(result.ProjectId, verseRef.BookNum, verseRef.ChapterNum))
CheckRunResults.RemoveAt(i);
}
}

/// <summary>
/// Given an indexed view of USFM text, determine the actual offsets to include for each result
/// </summary>
public void CalculateActualOffsets(UsfmBookIndexer indexer)
{
foreach (var result in CheckRunResults)
{
var verseIndex = indexer.GetIndex(result.Start.VerseRef);
if (!verseIndex.HasValue)
// Filter by ranges first to throw out whatever we can
if (ranges != null)
{
result.Start.Offset = 0;
continue;
var vref = result.Start.VerseRef;
bool isWithinAnyRange = false;
foreach (var range in ranges)
{
if (range.IsWithinRange(result.ProjectId, vref.BookNum, vref.ChapterNum))
{
isWithinAnyRange = true;
break;
}
}
if (!isWithinAnyRange)
{
CheckRunResults.RemoveAt(i);
continue;
}
}

var textIndex = indexer.Usfm.IndexOf(result.Text, verseIndex.Value);
if (textIndex < 0)
// Lookup whether a check was previously denied
if (denials != null)
{
result.Start.Offset = 0;
continue;
var isDenied = denials.IsDenied(
new Enum<MessageId>(result.CheckResultType),
result.VerseRef,
result.MessageFormatString,
result.Text
);
if (isDenied != result.IsDenied)
CheckRunResults[i] = new CheckRunResult(
result.CheckId,
result.CheckResultType,
result.ProjectId,
result.MessageFormatString,
result.Text,
isDenied,
result.VerseRef,
result.Start,
result.End
);
}

result.Start.Offset += textIndex - verseIndex.Value;
result.End.Offset = result.Start.Offset + result.Text.Length;
// Calculate actual offsets
if (indexer != null)
{
var verseIndex = indexer.GetIndex(result.Start.VerseRef);
if (!verseIndex.HasValue)
{
result.Start.Offset = 0;
continue;
}

var textIndex = indexer.Usfm.IndexOf(result.Text, verseIndex.Value);
if (textIndex < 0)
{
result.Start.Offset = 0;
continue;
}

result.Start.Offset += textIndex - verseIndex.Value;
result.End.Offset = result.Start.Offset + result.Text.Length;
}
}
}
}
59 changes: 26 additions & 33 deletions c-sharp/Checks/CheckRunResult.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,52 @@
using System.Text.Json.Serialization;
using SIL.Scripture;

namespace Paranext.DataProvider.Checks;

/// <summary>
/// Represents a single error/issue flagged by a check in a given project. This class must
/// serialize/deserialize to the CheckRunResult type defined in TypeScript.
/// </summary>
public sealed class CheckRunResult(
string checkId,
string projectId,
string messageFormatString,
string text,
CheckLocation start,
CheckLocation end
public sealed record CheckRunResult(
string CheckId,
string CheckResultType,
string ProjectId,
string MessageFormatString,
[property: JsonIgnore] string Text,
bool IsDenied,
VerseRef VerseRef,
CheckLocation Start,
CheckLocation End
) : IEquatable<CheckRunResult>
{
public string CheckId { get; } = checkId;
public string ProjectId { get; } = projectId;
public string MessageFormatString { get; } = messageFormatString;

[JsonIgnore]
public string Text { get; } = text;
public CheckLocation Start { get; } = start;
public CheckLocation End { get; } = end;

public override bool Equals(object? obj)
{
return obj is CheckRunResult checkRunResult && Equals(checkRunResult);
}

public bool Equals(CheckRunResult? other)
{
if (ReferenceEquals(other, null))
if (other is null)
return false;

return CheckId == other.CheckId
&& CheckResultType == other.CheckResultType
&& ProjectId == other.ProjectId
&& MessageFormatString == other.MessageFormatString
&& Text == other.Text
&& IsDenied == other.IsDenied
&& VerseRef.ToStringWithVersification() == other.VerseRef.ToStringWithVersification()
&& Start == other.Start
&& End == other.End;
}

public static bool operator ==(CheckRunResult a, CheckRunResult b)
{
return a.Equals(b);
}

public static bool operator !=(CheckRunResult a, CheckRunResult b)
{
return !(a == b);
}

public override int GetHashCode()
{
return HashCode.Combine(CheckId, ProjectId, MessageFormatString, Text, Start, End);
int hash = HashCode.Combine(
CheckId,
CheckResultType,
ProjectId,
MessageFormatString,
Text,
IsDenied,
VerseRef,
Start
);
return HashCode.Combine(hash, End);
}
}
Loading

0 comments on commit 927677e

Please sign in to comment.