Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions tools/StandardAnchorTags.Tests/ReferenceUpdateProcessorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@ public void DoesNotTreatFenceMentionsAsDelimiters(string line)
{
Assert.That(ReferenceUpdateProcessor.IsCodeFenceDelimiter(line), Is.False);
}

[Test]
public void RejectsSectionLinkWithoutClosingParenthesis()
{
const string line = "[§15.17](classes.md#1517-record-class-and-non-record-class-differences.";

var result = ReferenceUpdateProcessor.ExpandToIncludeExistingLink(line, new Range(1, 7));

Assert.That(result, Is.Null);
}
}
1 change: 1 addition & 0 deletions tools/StandardAnchorTags/DiagnosticIDs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ internal class DiagnosticIDs
{
public const string TOC001 = nameof(TOC001);
public const string TOC002 = nameof(TOC002);
public const string TOC003 = nameof(TOC003);
}
29 changes: 25 additions & 4 deletions tools/StandardAnchorTags/ReferenceUpdateProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,19 @@ private string ProcessSectionLinks(string line, int lineNumber, string path)
linkText = linkMap[referenceText].FormattedMarkdownLink;
}
// expand the range for any existing link:
sectionReferenceRange = ExpandToIncludeExistingLink(line, sectionReferenceRange);
if (ExpandToIncludeExistingLink(line, sectionReferenceRange) is not Range expandedRange)
{
var diagnostic = new StatusCheckMessage(
path,
lineNumber,
lineNumber,
$"Malformed section link for `{referenceText}`; expected `[section](target)`",
DiagnosticIDs.TOC003);
logger.LogFailure(diagnostic);
returnedLine.Append(line[index..]);
return returnedLine.ToString();
}
sectionReferenceRange = expandedRange;

var textRangeToCopyUnchanged = new Range(index, sectionReferenceRange.Start);
// Copy text up to replacement:
Expand Down Expand Up @@ -128,7 +140,7 @@ private string ProcessSectionLinks(string line, int lineNumber, string path)
return new Range(startIndex, endIndex);
}

private static Range ExpandToIncludeExistingLink(string line, Range range)
internal static Range? ExpandToIncludeExistingLink(string line, Range range)
{
// If the character before the start of the range isn't the '[' character,
// return => no existing link.
Expand All @@ -138,10 +150,19 @@ private static Range ExpandToIncludeExistingLink(string line, Range range)

// Start and the end of the range, look for "](", then ']'.
int endIndex = range.End.Value;
if (line.Substring(endIndex, 2) != "](") throw new InvalidOperationException($"Unexpected link text >{line.Substring(endIndex, 2)}< in line >{line}<");
if ((endIndex + 1 >= line.Length) ||
(line[endIndex] != ']') ||
(line[endIndex + 1] != '('))
{
return null;
}

endIndex += 2;
while (line[endIndex] != ')') endIndex++;
endIndex = line.IndexOf(')', endIndex);
if (endIndex == -1)
{
return null;
}

return new Range(previous, endIndex + 1);
}
Expand Down
28 changes: 28 additions & 0 deletions tools/Utilities.Tests/StatusCheckLoggerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Utilities;

namespace Utilities.Tests;

public class StatusCheckLoggerTests
{
[Test]
public void CheckRunLimitsAnnotationsAndSummarizesOmittedDiagnostics()
{
var output = new StringWriter();
var logger = new StatusCheckLogger(output, ".", "Test tool");

for (int i = 1; i <= 55; i++)
{
logger.LogWarning(new StatusCheckMessage("file.md", i, i, $"Warning {i}", "TEST001"));
}

var checkRun = logger.CreateCheckRun("head-sha");

Assert.Multiple(() =>
{
Assert.That(checkRun.Output.Annotations, Has.Count.EqualTo(StatusCheckLogger.MaximumAnnotations));
Assert.That(checkRun.Output.Summary, Does.Contain("55 diagnostics"));
Assert.That(checkRun.Output.Summary, Does.Contain("5 additional diagnostics"));
Assert.That(output.ToString(), Does.Contain("Warning 55"));
});
}
}
24 changes: 24 additions & 0 deletions tools/Utilities.Tests/Utilities.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.0" />
<PackageReference Include="NUnit" Version="4.6.1" />
<PackageReference Include="NUnit.Analyzers" Version="4.14.0" PrivateAssets="all" />
<PackageReference Include="NUnit3TestAdapter" Version="6.3.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Utilities\Utilities.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions tools/Utilities/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Utilities.Tests")]
33 changes: 24 additions & 9 deletions tools/Utilities/StatusCheckLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public record StatusCheckMessage(string file, int StartLine, int EndLine, string
/// <param name="toolName">The name of the tool that is running the check</param>
public class StatusCheckLogger(TextWriter writer, string pathToRoot, string toolName)
{
internal const int MaximumAnnotations = 50;

private List<NewCheckRunAnnotation> annotations = [];
public bool Success { get; private set; } = true;

Expand Down Expand Up @@ -155,15 +157,7 @@ public void ExitOnFailure(StatusCheckMessage d)
/// <returns>The full check run result object</returns>
public async Task BuildCheckRunResult(string token, string owner, string repo, string sha)
{
NewCheckRun result = new(toolName, sha)
{
Status = CheckStatus.Completed,
Conclusion = Success ? CheckConclusion.Success : CheckConclusion.Failure,
Output = new($"{toolName} Check Run results", $"{toolName} result is {(Success ? "success" : "failure")} with {annotations.Count} diagnostics.")
{
Annotations = annotations
}
};
NewCheckRun result = CreateCheckRun(sha);

var prodInformation = new ProductHeaderValue("TC49-TG2", "1.0.0");
var tokenAuth = new Credentials(token);
Expand All @@ -183,4 +177,25 @@ public async Task BuildCheckRunResult(string token, string owner, string repo, s
writer.WriteLine(e);
}
}

internal NewCheckRun CreateCheckRun(string sha)
{
var annotationsToSubmit = annotations.Take(MaximumAnnotations).ToList();
var omittedAnnotations = annotations.Count - annotationsToSubmit.Count;
var summary = $"{toolName} result is {(Success ? "success" : "failure")} with {annotations.Count} diagnostics.";
if (omittedAnnotations > 0)
{
summary += $" The first {MaximumAnnotations} diagnostics are annotated; {omittedAnnotations} additional diagnostics are available in the workflow log.";
}

return new(toolName, sha)
{
Status = CheckStatus.Completed,
Conclusion = Success ? CheckConclusion.Success : CheckConclusion.Failure,
Output = new($"{toolName} Check Run results", summary)
{
Annotations = annotationsToSubmit
}
};
}
}
14 changes: 14 additions & 0 deletions tools/tools.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleTester.Tests", "Exam
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandardAnchorTags.Tests", "StandardAnchorTags.Tests\StandardAnchorTags.Tests.csproj", "{DD0FB88E-0E16-45CD-A833-8BDD8EE197F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utilities.Tests", "Utilities.Tests\Utilities.Tests.csproj", "{284AC372-152E-4268-B435-9A122913BA0A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -142,6 +144,18 @@ Global
{DD0FB88E-0E16-45CD-A833-8BDD8EE197F0}.Release|x64.Build.0 = Release|Any CPU
{DD0FB88E-0E16-45CD-A833-8BDD8EE197F0}.Release|x86.ActiveCfg = Release|Any CPU
{DD0FB88E-0E16-45CD-A833-8BDD8EE197F0}.Release|x86.Build.0 = Release|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Debug|x64.ActiveCfg = Debug|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Debug|x64.Build.0 = Debug|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Debug|x86.ActiveCfg = Debug|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Debug|x86.Build.0 = Debug|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Release|Any CPU.Build.0 = Release|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Release|x64.ActiveCfg = Release|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Release|x64.Build.0 = Release|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Release|x86.ActiveCfg = Release|Any CPU
{284AC372-152E-4268-B435-9A122913BA0A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading