diff --git a/Directory.Build.props b/Directory.Build.props
index dbdcc82a..dec65c7d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -36,7 +36,7 @@
all
- 3.10.85
+ 3.10.91
diff --git a/modules/ModdingToolBase b/modules/ModdingToolBase
index 151cfb97..cc699325 160000
--- a/modules/ModdingToolBase
+++ b/modules/ModdingToolBase
@@ -1 +1 @@
-Subproject commit 151cfb97441442cf252fcb368dd3d423ddc5e078
+Subproject commit cc699325106a2aca3e1bf68e7015796602e66736
diff --git a/src/ModVerify/Reporting/Baseline/BaselineCollection.cs b/src/ModVerify/Reporting/Baseline/BaselineCollection.cs
index 6e9dda00..b3293fa8 100644
--- a/src/ModVerify/Reporting/Baseline/BaselineCollection.cs
+++ b/src/ModVerify/Reporting/Baseline/BaselineCollection.cs
@@ -7,16 +7,25 @@
namespace AET.ModVerify.Reporting.Baseline;
+/// Represents a set of identified verification baselines, each distinguished by a unique identifier.
public sealed class BaselineCollection : IReadOnlyCollection
{
+ /// Gets an empty that contains no baselines.
public static readonly BaselineCollection Empty = new([]);
private readonly IReadOnlyList _baselines;
+ ///
public int Count => _baselines.Count;
+ /// Gets a value that indicates whether the collection contains no baselines.
+ /// if the collection contains no baselines; otherwise, .
public bool IsEmpty => _baselines.Count == 0;
+ /// Initializes a new instance of the class with the specified baselines.
+ /// The identified baselines to include in the collection.
+ /// is .
+ /// An entry in is , or two entries share the same identifier.
public BaselineCollection(IEnumerable baselines)
{
if (baselines is null)
@@ -35,6 +44,9 @@ public BaselineCollection(IEnumerable baselines)
_baselines = list;
}
+ /// Determines whether any baseline in the collection contains the specified error.
+ /// The verification error to locate.
+ /// if a baseline in the collection contains ; otherwise, .
public bool Contains(VerificationError error)
{
foreach (var entry in _baselines)
@@ -45,6 +57,10 @@ public bool Contains(VerificationError error)
return false;
}
+ /// Gets the identifier of the first baseline in the collection that contains the specified error.
+ /// The verification error to locate.
+ /// When this method returns, contains the identifier of the matching baseline if a match was found, or if no baseline contains the error. This parameter is treated as uninitialized.
+ /// if a baseline containing was found; otherwise, .
public bool TryGetMatchingBaseline(VerificationError error, [NotNullWhen(true)] out string? identifier)
{
foreach (var entry in _baselines)
@@ -59,6 +75,10 @@ public bool TryGetMatchingBaseline(VerificationError error, [NotNullWhen(true)]
return false;
}
+ /// Filters out the errors that are contained in any baseline of the collection.
+ /// The errors to filter.
+ /// The errors that are not contained in any baseline of the collection.
+ /// is .
public IEnumerable Apply(IEnumerable errors)
{
if (errors is null)
@@ -68,6 +88,13 @@ public IEnumerable Apply(IEnumerable error
return errors.Where(e => !Contains(e));
}
+ /// Categorizes the specified errors into new, persistent, and resolved errors relative to the baselines in the collection.
+ /// The errors found during verification.
+ ///
+ /// The errors grouped into those not present in any baseline, those matching a baseline, and those present in a
+ /// baseline but not found again during verification.
+ ///
+ /// is .
public CategorizedVerificationErrors Categorize(IEnumerable errors)
{
if (errors is null)
@@ -102,6 +129,7 @@ public CategorizedVerificationErrors Categorize(IEnumerable e
new ReadOnlyValueListDictionary(resolved));
}
+ ///
public IEnumerator GetEnumerator()
{
return _baselines.GetEnumerator();
diff --git a/src/ModVerify/Reporting/Baseline/BaselineSource.cs b/src/ModVerify/Reporting/Baseline/BaselineSource.cs
index e018e418..7442927a 100644
--- a/src/ModVerify/Reporting/Baseline/BaselineSource.cs
+++ b/src/ModVerify/Reporting/Baseline/BaselineSource.cs
@@ -1,7 +1,10 @@
namespace AET.ModVerify.Reporting.Baseline;
+/// Specifies the origin of a verification baseline.
public enum BaselineSource
{
+ /// The baseline was loaded from a file on disk.
File,
+ /// The baseline is the default baseline embedded in the application.
EmbeddedDefault,
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Baseline/BaselineVerificationTarget.cs b/src/ModVerify/Reporting/Baseline/BaselineVerificationTarget.cs
index ca77fa85..dde29b5a 100644
--- a/src/ModVerify/Reporting/Baseline/BaselineVerificationTarget.cs
+++ b/src/ModVerify/Reporting/Baseline/BaselineVerificationTarget.cs
@@ -1,12 +1,27 @@
-using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Engine;
namespace AET.ModVerify.Reporting.Baseline;
+/// Represents the target that a verification baseline was created for.
public sealed record BaselineVerificationTarget
-{
+{
+ /// Gets or sets the game engine type of the target.
public required GameEngineType Engine { get; init; }
+
+ /// Gets or sets the name of the target.
public required string Name { get; init; }
- public GameLocations? Location { get; init; } // Optional compared to Verification Target
+
+ /// Gets or sets the game locations of the target, or if not specified.
+ /// The location is optional for a baseline target, unlike for a verification target.
+ public GameLocations? Location { get; init; }
+
+ /// Gets or sets the version of the target, or if not specified.
public string? Version { get; init; }
+
+ /// Gets or sets a value that indicates whether the target is the base game rather than a mod.
+ ///
+ /// if the target is the base game; otherwise, .
+ /// The default is .
+ ///
public bool IsGame { get; init; }
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Baseline/IdentifiedBaseline.cs b/src/ModVerify/Reporting/Baseline/IdentifiedBaseline.cs
index 7726d84c..97c34b10 100644
--- a/src/ModVerify/Reporting/Baseline/IdentifiedBaseline.cs
+++ b/src/ModVerify/Reporting/Baseline/IdentifiedBaseline.cs
@@ -2,14 +2,24 @@
namespace AET.ModVerify.Reporting.Baseline;
+/// Associates a verification baseline with a unique identifier and the source it was loaded from.
public sealed record IdentifiedBaseline
{
+ /// Gets the unique identifier of the baseline within its collection.
public string Identifier { get; }
+ /// Gets the verification baseline.
public VerificationBaseline Baseline { get; }
+ /// Gets the source the baseline was loaded from.
public BaselineSource Source { get; }
+ /// Initializes a new instance of the class.
+ /// The unique identifier of the baseline within its collection.
+ /// The verification baseline.
+ /// One of the enumeration values that specifies the source the baseline was loaded from.
+ /// is or empty.
+ /// is .
public IdentifiedBaseline(string identifier, VerificationBaseline baseline, BaselineSource source)
{
if (string.IsNullOrEmpty(identifier))
diff --git a/src/ModVerify/Reporting/Baseline/InvalidBaselineException.cs b/src/ModVerify/Reporting/Baseline/InvalidBaselineException.cs
index 58e180e4..79e0ddeb 100644
--- a/src/ModVerify/Reporting/Baseline/InvalidBaselineException.cs
+++ b/src/ModVerify/Reporting/Baseline/InvalidBaselineException.cs
@@ -1,7 +1,8 @@
-using System;
+using System;
namespace AET.ModVerify.Reporting.Baseline;
+/// The exception that is thrown when a verification baseline cannot be parsed or is otherwise invalid.
public sealed class InvalidBaselineException : Exception
{
internal InvalidBaselineException(string message) : base(message)
diff --git a/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs b/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs
index 80f95b8c..1cd26d0e 100644
--- a/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs
+++ b/src/ModVerify/Reporting/Baseline/VerificationBaseline.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
@@ -11,24 +11,34 @@
namespace AET.ModVerify.Reporting.Baseline;
+/// Represents a frozen set of verification errors that are already known and should be ignored during verification.
public sealed class VerificationBaseline : IReadOnlyCollection
{
+ /// Gets the latest supported baseline format version.
public static readonly Version LatestVersion = new(2, 2);
+
+ /// Gets the latest supported baseline format version as a string with two components.
public static readonly string LatestVersionString = LatestVersion.ToString(2);
+ /// Gets an empty that contains no errors.
public static readonly VerificationBaseline Empty = new(VerificationSeverity.Information, [], null);
private readonly HashSet _errors;
+ /// Gets the target that this baseline was created for, or if not specified.
public BaselineVerificationTarget? Target { get; }
-
+
+ /// Gets the format version of this baseline, or if unknown.
public Version? Version { get; }
+ /// Gets the minimum severity of the errors recorded in this baseline.
public VerificationSeverity MinimumSeverity { get; }
///
public int Count => _errors.Count;
+ /// Gets a value that indicates whether the baseline contains no errors.
+ /// if the baseline contains no errors; otherwise, .
public bool IsEmpty => Count == 0;
internal VerificationBaseline(JsonVerificationBaseline baseline)
@@ -39,33 +49,55 @@ internal VerificationBaseline(JsonVerificationBaseline baseline)
Target = JsonVerificationTarget.ToTarget(baseline.Target);
}
+ /// Initializes a new instance of the class.
+ /// One of the enumeration values that specifies the minimum severity of the errors recorded in the baseline.
+ /// The errors to record in the baseline.
+ /// The target the baseline was created for, or if not specified.
+ /// is .
public VerificationBaseline(VerificationSeverity minimumSeverity, IEnumerable errors, BaselineVerificationTarget? target)
{
+ if (errors == null) throw new ArgumentNullException(nameof(errors));
_errors = [..errors];
Version = LatestVersion;
MinimumSeverity = minimumSeverity;
Target = target;
}
+ /// Determines whether the baseline contains the specified error.
+ /// The verification error to locate.
+ /// if the baseline contains ; otherwise, .
public bool Contains(VerificationError error)
{
return _errors.Contains(error);
}
+ /// Filters out the errors that are contained in the baseline.
+ /// The errors to filter.
+ /// The errors that are not contained in the baseline.
public IEnumerable Apply(IEnumerable errors)
{
return Count == 0 ? errors : errors.Where(e => !_errors.Contains(e));
}
+ /// Serializes the baseline as JSON to the specified stream.
+ /// The stream to write the JSON representation to.
public void ToJson(Stream stream)
{
JsonSerializer.Serialize(stream, new JsonVerificationBaseline(this), ModVerifyJsonSettings.JsonSettings);
}
+
+ /// Asynchronously serializes the baseline as JSON to the specified stream.
+ /// The stream to write the JSON representation to.
+ /// A task that represents the asynchronous serialization operation.
public Task ToJsonAsync(Stream stream)
{
return JsonSerializer.SerializeAsync(stream, new JsonVerificationBaseline(this), ModVerifyJsonSettings.JsonSettings);
}
+ /// Deserializes a baseline from its JSON representation.
+ /// The stream to read the JSON representation from.
+ /// The deserialized baseline.
+ /// The JSON representation is invalid or cannot be parsed.
public static VerificationBaseline FromJson(Stream stream)
{
return JsonBaselineParser.Parse(stream);
@@ -82,6 +114,7 @@ IEnumerator IEnumerable.GetEnumerator()
return GetEnumerator();
}
+ ///
public override string ToString()
{
var sb = new StringBuilder($"Baseline [Version={Version}, MinSeverity={MinimumSeverity}, NumErrors={Count}");
diff --git a/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs b/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs
index f8c7cd28..f99be722 100644
--- a/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs
+++ b/src/ModVerify/Reporting/Engine/EngineErrorReporterBase.cs
@@ -15,7 +15,7 @@ internal abstract class EngineErrorReporterBase : IGameVerifierInfo
public IReadOnlyList VerifierChain { get; }
- public string Name => GetType().FullName;
+ public string Name => GetType().FullName!;
public abstract string FriendlyName { get; }
diff --git a/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs b/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs
index 8cb67c06..251debcb 100644
--- a/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs
+++ b/src/ModVerify/Reporting/Engine/GameEngineErrorCollection.cs
@@ -1,4 +1,4 @@
-using System.Collections.Concurrent;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using PG.StarWarsGame.Engine.ErrorReporting;
@@ -6,16 +6,20 @@
namespace AET.ModVerify.Reporting.Engine;
+/// Collects the XML, initialization, and assertion errors reported by the game engine during verification.
public sealed class GameEngineErrorCollection : IGameEngineErrorCollection, IGameEngineErrorReporter
{
- private readonly ConcurrentBag _xmlErrors = new();
- private readonly ConcurrentBag _initializationErrors = new();
- private readonly ConcurrentBag _asserts = new();
+ private readonly ConcurrentBag _xmlErrors = [];
+ private readonly ConcurrentBag _initializationErrors = [];
+ private readonly ConcurrentBag _asserts = [];
+ ///
public IEnumerable XmlErrors => _xmlErrors.ToList();
+ ///
public IEnumerable InitializationErrors => _initializationErrors.ToList();
+ ///
public IEnumerable Asserts => _asserts.ToList();
void IXmlParserErrorReporter.Report(XmlError error)
diff --git a/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs b/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs
index 286d047d..7c1d8b5e 100644
--- a/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs
+++ b/src/ModVerify/Reporting/Engine/IGameEngineErrorCollection.cs
@@ -1,12 +1,18 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using PG.StarWarsGame.Engine.ErrorReporting;
using PG.StarWarsGame.Files.XML.ErrorHandling;
namespace AET.ModVerify.Reporting.Engine;
+/// Provides the errors and assertions collected from the game engine during verification.
public interface IGameEngineErrorCollection
{
+ /// Gets the XML parser errors reported by the engine.
IEnumerable XmlErrors { get; }
+
+ /// Gets the initialization errors reported by the engine.
IEnumerable InitializationErrors { get; }
+
+ /// Gets the assertions raised by the engine.
IEnumerable Asserts { get; }
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Reporters/Console/ConsoleReporter.cs b/src/ModVerify/Reporting/Reporters/Console/ConsoleReporter.cs
index 79892f70..f4a1a1ac 100644
--- a/src/ModVerify/Reporting/Reporters/Console/ConsoleReporter.cs
+++ b/src/ModVerify/Reporting/Reporters/Console/ConsoleReporter.cs
@@ -78,11 +78,12 @@ private void PrintResolvedStats(VerificationResult verificationResult)
$"Reduced issues: {resolvedCount} error(s) present in the baseline are no longer reported.");
Console.ResetColor();
- if (Settings.Verbose
#if DEBUG
- || true
+ const bool debugBuild = true;
+#else
+ const bool debugBuild = false;
#endif
- )
+ if (Settings.Verbose || debugBuild)
{
foreach (var baseline in resolvedErrors)
{
diff --git a/src/ModVerify/Reporting/Reporters/Console/ConsoleReporterSettings.cs b/src/ModVerify/Reporting/Reporters/Console/ConsoleReporterSettings.cs
index 4dc2a774..156c3390 100644
--- a/src/ModVerify/Reporting/Reporters/Console/ConsoleReporterSettings.cs
+++ b/src/ModVerify/Reporting/Reporters/Console/ConsoleReporterSettings.cs
@@ -1,6 +1,12 @@
-namespace AET.ModVerify.Reporting.Reporters;
+namespace AET.ModVerify.Reporting.Reporters;
+/// Provides the settings for the console verification reporter.
public sealed record ConsoleReporterSettings : ReporterSettings
{
+ /// Gets or sets a value that indicates whether only a summary is written to the console instead of individual findings.
+ ///
+ /// to write only a summary; otherwise, to write individual findings.
+ /// The default is .
+ ///
public bool SummaryOnly { get; init; }
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Reporters/ExtensionMethods.cs b/src/ModVerify/Reporting/Reporters/ExtensionMethods.cs
index 480e956a..27c8ded3 100644
--- a/src/ModVerify/Reporting/Reporters/ExtensionMethods.cs
+++ b/src/ModVerify/Reporting/Reporters/ExtensionMethods.cs
@@ -1,31 +1,50 @@
-using System;
+using System;
namespace AET.ModVerify.Reporting.Reporters;
+/// Provides factory methods for creating verification reporters.
public static class ExtensionMethods
{
extension(IVerificationReporter)
{
+ /// Creates a JSON reporter with default settings.
+ /// The service provider used to resolve dependencies.
+ /// A new JSON reporter.
public static IVerificationReporter CreateJson(IServiceProvider serviceProvider)
{
return IVerificationReporter.CreateJson(new JsonReporterSettings(), serviceProvider);
}
+ /// Creates a JSON reporter with the specified settings.
+ /// The settings that control the reporter's behavior.
+ /// The service provider used to resolve dependencies.
+ /// A new JSON reporter.
public static IVerificationReporter CreateJson(JsonReporterSettings settings, IServiceProvider serviceProvider)
{
return new JsonReporter(settings, serviceProvider);
}
+ /// Creates a text-file reporter with default settings.
+ /// The service provider used to resolve dependencies.
+ /// A new text-file reporter.
public static IVerificationReporter CreateText(IServiceProvider serviceProvider)
{
return IVerificationReporter.CreateText(new TextFileReporterSettings(), serviceProvider);
}
+ /// Creates a text-file reporter with the specified settings.
+ /// The settings that control the reporter's behavior.
+ /// The service provider used to resolve dependencies.
+ /// A new text-file reporter.
public static IVerificationReporter CreateText(TextFileReporterSettings settings, IServiceProvider serviceProvider)
{
return new TextFileReporter(settings, serviceProvider);
}
+ /// Creates a console reporter that reports findings with a severity of or higher.
+ /// The service provider used to resolve dependencies.
+ /// to write only a summary; otherwise, to write individual findings.
+ /// A new console reporter.
public static IVerificationReporter CreateConsole(IServiceProvider serviceProvider, bool summaryOnly = false)
{
var settings = new ConsoleReporterSettings
@@ -36,6 +55,10 @@ public static IVerificationReporter CreateConsole(IServiceProvider serviceProvid
return IVerificationReporter.CreateConsole(settings, serviceProvider);
}
+ /// Creates a console reporter with the specified settings.
+ /// The settings that control the reporter's behavior.
+ /// The service provider used to resolve dependencies.
+ /// A new console reporter.
public static IVerificationReporter CreateConsole(ConsoleReporterSettings settings, IServiceProvider serviceProvider)
{
return new ConsoleReporter(settings, serviceProvider);
diff --git a/src/ModVerify/Reporting/Reporters/FileBasedReporter.cs b/src/ModVerify/Reporting/Reporters/FileBasedReporter.cs
index 4c60121a..026b4d1e 100644
--- a/src/ModVerify/Reporting/Reporters/FileBasedReporter.cs
+++ b/src/ModVerify/Reporting/Reporters/FileBasedReporter.cs
@@ -1,15 +1,22 @@
-using System;
+using System;
using System.IO;
using System.IO.Abstractions;
using Microsoft.Extensions.DependencyInjection;
namespace AET.ModVerify.Reporting.Reporters;
-public abstract class FileBasedReporter(T settings, IServiceProvider serviceProvider)
+/// Provides a base class for verification reporters that write their output to files.
+/// The type of settings used by the reporter.
+/// The settings that control the reporter's behavior.
+/// The service provider used to resolve dependencies.
+public abstract class FileBasedReporter(T settings, IServiceProvider serviceProvider)
: ReporterBase(settings, serviceProvider) where T : FileBasedReporterSettings
{
private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService();
+ /// Creates a writable file stream for the specified file name in the configured output directory.
+ /// The name of the file to create.
+ /// A writable stream for the newly created file.
protected Stream CreateFile(string fileName)
{
var outputDirectory = Settings.OutputDirectory;
diff --git a/src/ModVerify/Reporting/Reporters/FileBasedReporterSettings.cs b/src/ModVerify/Reporting/Reporters/FileBasedReporterSettings.cs
index aa468fcc..d2da5335 100644
--- a/src/ModVerify/Reporting/Reporters/FileBasedReporterSettings.cs
+++ b/src/ModVerify/Reporting/Reporters/FileBasedReporterSettings.cs
@@ -1,9 +1,13 @@
-using System;
+using System;
namespace AET.ModVerify.Reporting.Reporters;
+/// Provides the settings shared by file-based verification reporters.
public record FileBasedReporterSettings : ReporterSettings
{
+ /// Gets or sets the directory that report files are written to.
+ /// The directory that report files are written to. The default is the current working directory.
+ /// Setting the value to or an empty string resets it to the current working directory.
public string OutputDirectory
{
get;
diff --git a/src/ModVerify/Reporting/Reporters/IVerificationReporter.cs b/src/ModVerify/Reporting/Reporters/IVerificationReporter.cs
index 5ce7a650..660f4394 100644
--- a/src/ModVerify/Reporting/Reporters/IVerificationReporter.cs
+++ b/src/ModVerify/Reporting/Reporters/IVerificationReporter.cs
@@ -1,8 +1,12 @@
-using System.Threading.Tasks;
+using System.Threading.Tasks;
namespace AET.ModVerify.Reporting.Reporters;
-public interface IVerificationReporter
+/// Defines a reporter that writes a verification result to an output sink.
+public interface IVerificationReporter
{
+ /// Asynchronously reports the specified verification result.
+ /// The verification result to report.
+ /// A task that represents the asynchronous report operation.
public Task ReportAsync(VerificationResult verificationResult);
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs b/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs
index a2503ed5..08bf836b 100644
--- a/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs
+++ b/src/ModVerify/Reporting/Reporters/JSON/JsonReporterSettings.cs
@@ -1,5 +1,12 @@
-namespace AET.ModVerify.Reporting.Reporters;
+namespace AET.ModVerify.Reporting.Reporters;
+
+/// Provides the settings for the JSON verification reporter.
public record JsonReporterSettings : FileBasedReporterSettings
{
+ /// Gets or sets a value that indicates whether errors are aggregated in the JSON report.
+ ///
+ /// if errors are aggregated; otherwise, .
+ /// The default is .
+ ///
public bool AggregateResults { get; init; }
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Reporters/ReporterBase.cs b/src/ModVerify/Reporting/Reporters/ReporterBase.cs
index 47cafc5e..fdfb6bf3 100644
--- a/src/ModVerify/Reporting/Reporters/ReporterBase.cs
+++ b/src/ModVerify/Reporting/Reporters/ReporterBase.cs
@@ -1,18 +1,29 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AET.ModVerify.Reporting.Reporters;
+/// Provides a base class for verification reporters that share settings and access to services.
+/// The type of settings used by the reporter.
+/// The settings that control the reporter's behavior.
+/// The service provider used to resolve dependencies.
+/// or is .
public abstract class ReporterBase(T settings, IServiceProvider serviceProvider) : IVerificationReporter where T : ReporterSettings
{
+ /// Gets the service provider used to resolve dependencies.
protected IServiceProvider ServiceProvider { get; } = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+ /// Gets the settings that control the reporter's behavior.
protected T Settings { get; } = settings ?? throw new ArgumentNullException(nameof(settings));
+ ///
public abstract Task ReportAsync(VerificationResult verificationResult);
+ /// Filters the specified errors to those meeting the configured minimum report severity.
+ /// The errors to filter.
+ /// The errors whose severity is at least .
protected IEnumerable FilteredErrors(IReadOnlyCollection errors)
{
return errors.Where(x => x.Severity >= Settings.MinimumReportSeverity);
diff --git a/src/ModVerify/Reporting/Reporters/ReporterSettings.cs b/src/ModVerify/Reporting/Reporters/ReporterSettings.cs
index 6cd56d3d..633c446f 100644
--- a/src/ModVerify/Reporting/Reporters/ReporterSettings.cs
+++ b/src/ModVerify/Reporting/Reporters/ReporterSettings.cs
@@ -1,7 +1,16 @@
-namespace AET.ModVerify.Reporting.Reporters;
+namespace AET.ModVerify.Reporting.Reporters;
+/// Provides the base settings shared by all verification reporters.
public record ReporterSettings
{
+ /// Gets or sets the minimum severity a finding must have to be reported.
+ /// The minimum severity of reported findings. The default is .
public VerificationSeverity MinimumReportSeverity { get; init; } = VerificationSeverity.Information;
+
+ /// Gets or sets a value that indicates whether the reporter emits verbose output.
+ ///
+ /// if the reporter emits verbose output; otherwise, .
+ /// The default is .
+ ///
public bool Verbose { get; init; }
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Reporters/Text/TextFileReporterSettings.cs b/src/ModVerify/Reporting/Reporters/Text/TextFileReporterSettings.cs
index 2d0e3488..c81b8cdd 100644
--- a/src/ModVerify/Reporting/Reporters/Text/TextFileReporterSettings.cs
+++ b/src/ModVerify/Reporting/Reporters/Text/TextFileReporterSettings.cs
@@ -1,6 +1,12 @@
-namespace AET.ModVerify.Reporting.Reporters;
+namespace AET.ModVerify.Reporting.Reporters;
+/// Provides the settings for the text-file verification reporter.
public sealed record TextFileReporterSettings : FileBasedReporterSettings
{
+ /// Gets or sets a value that indicates whether findings are split across multiple files instead of written to a single file.
+ ///
+ /// to split findings across multiple files; otherwise, to write a single file.
+ /// The default is .
+ ///
public bool SplitIntoFiles { get; init; } = true;
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Reporters/VerificationReportBroker.cs b/src/ModVerify/Reporting/Reporters/VerificationReportBroker.cs
index 0ea6630b..6c16cdc9 100644
--- a/src/ModVerify/Reporting/Reporters/VerificationReportBroker.cs
+++ b/src/ModVerify/Reporting/Reporters/VerificationReportBroker.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
@@ -6,11 +6,16 @@
namespace AET.ModVerify.Reporting.Reporters;
+/// Distributes a verification result to multiple reporters, isolating the failure of any individual reporter.
public sealed class VerificationReportBroker : IVerificationReporter
{
private readonly ILogger? _logger;
private readonly IReadOnlyCollection _reporters;
+ /// Initializes a new instance of the class.
+ /// The reporters to distribute the verification result to.
+ /// The service provider used to resolve a logger.
+ /// is .
public VerificationReportBroker(
IReadOnlyCollection reporters,
IServiceProvider serviceProvider)
@@ -19,6 +24,8 @@ public VerificationReportBroker(
_logger = serviceProvider.GetService()?.CreateLogger(typeof(VerificationReportBroker));
}
+ ///
+ /// An exception thrown by an individual reporter is logged and does not prevent the remaining reporters from running.
public async Task ReportAsync(VerificationResult result)
{
foreach (var reporter in _reporters)
@@ -29,7 +36,7 @@ public async Task ReportAsync(VerificationResult result)
}
catch (Exception e)
{
- _logger?.LogError(e, "Exception while reporting verification error");
+ _logger?.LogError(e, "Exception while reporting verification error. Reporter: {Reporter}", reporter.GetType().FullName);
}
}
}
diff --git a/src/ModVerify/Reporting/Suppressions/SuppressionFilter.cs b/src/ModVerify/Reporting/Suppressions/SuppressionFilter.cs
index 35a21d7a..2bbfcc2d 100644
--- a/src/ModVerify/Reporting/Suppressions/SuppressionFilter.cs
+++ b/src/ModVerify/Reporting/Suppressions/SuppressionFilter.cs
@@ -1,19 +1,29 @@
-using System;
+using System;
using System.Linq;
using AET.ModVerify.Reporting.Suppressions.Json;
namespace AET.ModVerify.Reporting.Suppressions;
+/// Represents a filter that suppresses verification errors matching a combination of error identifier, verifier, and asset.
public sealed class SuppressionFilter : IEquatable
{
+ /// Gets the error identifier to match, or to match any identifier.
public string? Id { get; }
+ /// Gets the verifier name to match, or to match any verifier.
public string? Verifier { get; }
+ /// Gets the asset to match, or to match any asset.
public string? Asset { get; }
+ /// Gets a value that indicates whether the filter is disabled because no matching criterion is set.
+ /// if none of , , and is set; otherwise, .
public bool IsDisabled => Id == null && Verifier == null && Asset == null;
+ /// Initializes a new instance of the class.
+ /// The error identifier to match, or to match any identifier.
+ /// The verifier name to match, or to match any verifier.
+ /// The asset to match, or to match any asset.
public SuppressionFilter(string? id, string? verifier, string? asset)
{
Id = id;
@@ -28,6 +38,9 @@ internal SuppressionFilter(JsonSuppressionFilter filter)
Asset = filter.Asset;
}
+ /// Determines whether this filter suppresses the specified error.
+ /// The verification error to test.
+ /// if the filter suppresses ; otherwise, .
public bool Suppresses(VerificationError error)
{
var suppresses = false;
@@ -59,32 +72,7 @@ public bool Suppresses(VerificationError error)
return suppresses;
}
- public int Specificity()
- {
- var specificity = 0;
- if (Id != null)
- specificity++;
- if (Verifier != null)
- specificity++;
- if (Asset != null)
- specificity++;
- return specificity;
- }
-
- public bool IsSupersededBy(SuppressionFilter other)
- {
- if (Id != null && other.Id != null && other.Id != Id)
- return false;
-
- if (Verifier != null && other.Verifier != null && other.Verifier != Verifier)
- return false;
-
- if (Asset != null && other.Asset != null)
- return false;
-
- return other.Specificity() < Specificity();
- }
-
+ ///
public bool Equals(SuppressionFilter? other)
{
if (ReferenceEquals(null, other))
@@ -99,11 +87,13 @@ public bool Equals(SuppressionFilter? other)
return Asset == other.Asset;
}
+ ///
public override bool Equals(object? obj)
{
return obj is SuppressionFilter other && Equals(other);
}
+ ///
public override int GetHashCode()
{
var hashCode = new HashCode();
diff --git a/src/ModVerify/Reporting/Suppressions/SuppressionList.cs b/src/ModVerify/Reporting/Suppressions/SuppressionList.cs
index a5fc8f9a..0d3588fb 100644
--- a/src/ModVerify/Reporting/Suppressions/SuppressionList.cs
+++ b/src/ModVerify/Reporting/Suppressions/SuppressionList.cs
@@ -1,4 +1,4 @@
-using AET.ModVerify.Reporting.Json;
+using AET.ModVerify.Reporting.Json;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -9,22 +9,26 @@
namespace AET.ModVerify.Reporting.Suppressions;
+/// Represents a set of suppression filters that remove known verification errors from a result.
public sealed class SuppressionList : IReadOnlyCollection
{
+ /// Gets an empty that suppresses nothing.
public static readonly SuppressionList Empty = new([]);
private readonly IReadOnlyCollection _filters;
- private readonly IReadOnlyCollection _minimizedFilters;
+ ///
public int Count => _filters.Count;
+ /// Initializes a new instance of the class with the specified filters.
+ /// The suppression filters to include in the list.
+ /// is .
public SuppressionList(IEnumerable suppressionFilters)
{
- if (suppressionFilters == null)
+ if (suppressionFilters == null)
throw new ArgumentNullException(nameof(suppressionFilters));
_filters = [..suppressionFilters];
- _minimizedFilters = MinimizeSuppressions(_filters);
}
internal SuppressionList(JsonSuppressionList suppressionList)
@@ -33,14 +37,19 @@ internal SuppressionList(JsonSuppressionList suppressionList)
throw new ArgumentNullException(nameof(suppressionList));
_filters = suppressionList.Filters.Select(x => new SuppressionFilter(x)).ToList();
- _minimizedFilters = MinimizeSuppressions(_filters);
}
+ /// Serializes the suppression list as JSON to the specified stream.
+ /// The stream to write the JSON representation to.
public void ToJson(Stream stream)
{
JsonSerializer.Serialize(stream, new JsonSuppressionList(this), ModVerifyJsonSettings.JsonSettings);
}
+ /// Deserializes a suppression list from its JSON representation.
+ /// The stream to read the JSON representation from.
+ /// The deserialized suppression list.
+ /// The JSON representation cannot be deserialized.
public static SuppressionList FromJson(Stream stream)
{
var baselineJson = JsonSerializer.Deserialize(stream, JsonSerializerOptions.Default);
@@ -49,14 +58,20 @@ public static SuppressionList FromJson(Stream stream)
return new SuppressionList(baselineJson);
}
+ /// Filters out the errors that are suppressed by any filter in the list.
+ /// The errors to filter.
+ /// The errors that are not suppressed by any filter in the list.
public IEnumerable Apply(IEnumerable errors)
{
return Count == 0 ? errors : errors.Where(e => !Suppresses(e));
}
+ /// Determines whether any filter in the list suppresses the specified error.
+ /// The verification error to test.
+ /// if a filter in the list suppresses ; otherwise, .
public bool Suppresses(VerificationError error)
{
- foreach (var filter in _minimizedFilters)
+ foreach (var filter in _filters)
{
if (filter.Suppresses(error))
{
@@ -67,22 +82,7 @@ public bool Suppresses(VerificationError error)
return false;
}
- private static IReadOnlyCollection MinimizeSuppressions(IEnumerable filters)
- {
- var sortedFilters = filters.Where(f => !f.IsDisabled)
- .OrderBy(x => x.Specificity());
-
- var result = new List();
-
- foreach (var filter in sortedFilters)
- {
- if (result.All(x => !filter.IsSupersededBy(x)))
- result.Add(filter);
- }
-
- return result;
- }
-
+ ///
public IEnumerator GetEnumerator()
{
return _filters.GetEnumerator();
diff --git a/src/ModVerify/Verifiers/Caching/IAlreadyVerifiedCache.cs b/src/ModVerify/Verifiers/Caching/IAlreadyVerifiedCache.cs
index 68f39b40..e7707b55 100644
--- a/src/ModVerify/Verifiers/Caching/IAlreadyVerifiedCache.cs
+++ b/src/ModVerify/Verifiers/Caching/IAlreadyVerifiedCache.cs
@@ -1,8 +1,25 @@
-namespace AET.ModVerify.Verifiers.Caching;
+namespace AET.ModVerify.Verifiers.Caching;
+/// Provides a cache that tracks which assets have already been verified within a single verification run.
public interface IAlreadyVerifiedCache
{
+ /// Adds an entry to the cache if it is not already present.
+ /// The identifier of the asset, such as a file name.
+ ///
+ /// When this method returns, contains a value indicating whether the asset was found.
+ /// if the asset was found; otherwise, .
+ ///
+ ///
+ /// if the entry was added;
+ /// if an entry for already existed.
+ ///
bool TryAddEntry(string entry, bool assetExists);
+ /// Gets the cache entry for the specified asset.
+ /// The identifier of the asset, such as a file name.
+ ///
+ /// The cache entry, or a default entry whose is
+ /// if the asset has not been verified.
+ ///
VerifiedCacheEntry GetEntry(string entry);
}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/Caching/VerifiedCacheEntry.cs b/src/ModVerify/Verifiers/Caching/VerifiedCacheEntry.cs
index 252a7c09..c35f32a8 100644
--- a/src/ModVerify/Verifiers/Caching/VerifiedCacheEntry.cs
+++ b/src/ModVerify/Verifiers/Caching/VerifiedCacheEntry.cs
@@ -1,11 +1,19 @@
-namespace AET.ModVerify.Verifiers.Caching;
+namespace AET.ModVerify.Verifiers.Caching;
+/// Represents the result of a lookup in an .
public readonly struct VerifiedCacheEntry
{
+ /// Gets a value that indicates whether the asset has already been verified.
+ /// if the asset has already been verified; otherwise, .
public bool AlreadyVerified { get; }
+ /// Gets a value that indicates whether the asset was found during its earlier verification.
+ /// if the asset was found; otherwise, .
public bool AssetExists { get; }
+ /// Initializes a new instance of the struct.
+ /// if the asset has already been verified; otherwise, .
+ /// if the asset was found; otherwise, .
public VerifiedCacheEntry(bool alreadyVerified, bool assetExists)
{
AlreadyVerified = alreadyVerified;
diff --git a/src/ModVerify/Verifiers/Commons/Duplicates/IDuplicateVerificationContext.cs b/src/ModVerify/Verifiers/Commons/Duplicates/IDuplicateVerificationContext.cs
index 4301e543..24d7b95c 100644
--- a/src/ModVerify/Verifiers/Commons/Duplicates/IDuplicateVerificationContext.cs
+++ b/src/ModVerify/Verifiers/Commons/Duplicates/IDuplicateVerificationContext.cs
@@ -1,11 +1,23 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using PG.Commons.Hashing;
namespace AET.ModVerify.Verifiers.Commons;
+/// Provides the data a duplicate verifier needs to detect duplicate entries within a source.
public interface IDuplicateVerificationContext
{
+ /// Gets the name of the source being checked for duplicates.
string SourceName { get; }
+
+ /// Gets the CRC-32 checksums of the entries in the source.
+ /// The checksums of all entries.
IEnumerable GetCrcs();
+
+ /// Determines whether the entry with the specified checksum has duplicates.
+ /// The checksum of the entry to check.
+ /// When this method returns, contains the name of the entry. This parameter is treated as uninitialized.
+ /// When this method returns, contains the context entries describing the duplicates. This parameter is treated as uninitialized.
+ /// When this method returns, contains the message describing the duplication. This parameter is treated as uninitialized.
+ /// if the entry has duplicates; otherwise, .
bool HasDuplicates(Crc32 crc, out string entryNames, out IEnumerable duplicateContext, out string errorMessage);
}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameVerifier.cs b/src/ModVerify/Verifiers/GameVerifier.cs
index 83871d99..66ba9021 100644
--- a/src/ModVerify/Verifiers/GameVerifier.cs
+++ b/src/ModVerify/Verifiers/GameVerifier.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Threading;
using AET.ModVerify.Settings;
@@ -6,8 +6,15 @@
namespace AET.ModVerify.Verifiers;
+/// Provides the base class for verifiers that verify individual entities of a given type.
+/// The type of entity to verify.
public abstract class GameVerifier : GameVerifierBase where T : notnull
{
+ /// Initializes a new instance of the class.
+ /// The parent verifier, or if this is a root verifier.
+ /// The game engine to verify against.
+ /// The settings that control the verification run.
+ /// The service provider used to resolve dependencies.
protected GameVerifier(
IGameVerifierInfo? parent,
IStarWarsGameEngine gameEngine,
@@ -15,10 +22,17 @@ protected GameVerifier(
IServiceProvider serviceProvider) : base(parent, gameEngine, settings, serviceProvider)
{
}
+
+ /// Initializes a new instance of the class as a child of the specified parent verifier.
+ /// The parent verifier whose engine, settings, and services are inherited.
protected GameVerifier(GameVerifierBase parent) : base(parent)
{
}
+ /// Initializes a new instance of the class as a root verifier.
+ /// The game engine to verify against.
+ /// The settings that control the verification run.
+ /// The service provider used to resolve dependencies.
protected GameVerifier(
IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
@@ -26,23 +40,40 @@ protected GameVerifier(
{
}
+ /// Verifies the specified entity.
+ /// The entity to verify.
+ /// Context entries describing where the entity was found, used for error reporting.
+ /// The token to monitor for cancellation requests.
public abstract void Verify(T toVerify, IReadOnlyCollection contextInfo, CancellationToken token);
}
+/// Provides the base class for verifiers that perform a single verification pass.
public abstract class GameVerifier : GameVerifierBase
{
+ /// Initializes a new instance of the class.
+ /// The parent verifier, or if this is a root verifier.
+ /// The game engine to verify against.
+ /// The settings that control the verification run.
+ /// The service provider used to resolve dependencies.
protected GameVerifier(
IGameVerifierInfo? parent,
IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
- IServiceProvider serviceProvider)
+ IServiceProvider serviceProvider)
: base(parent, gameEngine, settings, serviceProvider)
{
}
+
+ /// Initializes a new instance of the class as a child of the specified parent verifier.
+ /// The parent verifier whose engine, settings, and services are inherited.
protected GameVerifier(GameVerifierBase parent) : base(parent)
{
}
+ /// Initializes a new instance of the class as a root verifier.
+ /// The game engine to verify against.
+ /// The settings that control the verification run.
+ /// The service provider used to resolve dependencies.
protected GameVerifier(
IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
@@ -51,5 +82,7 @@ protected GameVerifier(
{
}
+ /// Runs the verification.
+ /// The token to monitor for cancellation requests.
public abstract void Verify(CancellationToken token);
}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/GameVerifierBase.cs b/src/ModVerify/Verifiers/GameVerifierBase.cs
index 2da47bc6..90ead1bb 100644
--- a/src/ModVerify/Verifiers/GameVerifierBase.cs
+++ b/src/ModVerify/Verifiers/GameVerifierBase.cs
@@ -1,4 +1,4 @@
-using AET.ModVerify.Reporting;
+using AET.ModVerify.Reporting;
using AET.ModVerify.Settings;
using AnakinRaW.CommonUtilities.SimplePipeline.Progress;
using Microsoft.Extensions.DependencyInjection;
@@ -15,40 +15,65 @@
namespace AET.ModVerify.Verifiers;
+/// Provides the base class for game verifiers, handling error collection, progress reporting, and access to the game engine.
public abstract class GameVerifierBase : IGameVerifierInfo
{
+ /// Occurs when the verifier reports a new verification error.
public event EventHandler? Error;
- public event EventHandler>? Progress;
+
+ /// Occurs when the verifier reports progress.
+ public event EventHandler>? Progress;
private readonly ConcurrentDictionary _verifyErrors = new();
+ /// The file system used by the verifier.
protected readonly IFileSystem FileSystem;
+
+ /// The service provider used to resolve dependencies.
protected readonly IServiceProvider Services;
+
+ /// The settings that control the verification run.
protected readonly GameVerifySettings Settings;
+
+ /// The logger used by the verifier.
protected readonly ILogger Logger;
+ /// Gets the verification errors collected by this verifier.
public IReadOnlyCollection VerifyErrors => [.. _verifyErrors.Keys];
+ ///
+ /// The default implementation returns the runtime type name.
public virtual string FriendlyName => GetType().Name;
- public string Name => GetType().FullName;
+ ///
+ public string Name => GetType().FullName!;
+ ///
public IGameVerifierInfo? Parent { get; }
+ /// Gets the game engine that the verifier runs against.
protected IStarWarsGameEngine GameEngine { get; }
+ /// Gets the game repository of the .
protected IGameRepository Repository => GameEngine.GameRepository;
+ ///
public IReadOnlyList VerifierChain { get; }
- protected GameVerifierBase(GameVerifierBase parent)
+ /// Initializes a new instance of the class as a child of the specified parent verifier.
+ /// The parent verifier whose engine, settings, and services are inherited.
+ protected GameVerifierBase(GameVerifierBase parent)
: this(parent, parent.GameEngine, parent.Settings, parent.Services)
{
if (parent == null)
throw new ArgumentNullException(nameof(parent));
}
+ /// Initializes a new instance of the class as a root verifier.
+ /// The game engine to verify against.
+ /// The settings that control the verification run.
+ /// The service provider used to resolve dependencies.
protected GameVerifierBase(
IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
@@ -57,6 +82,12 @@ protected GameVerifierBase(
{
}
+ /// Initializes a new instance of the class.
+ /// The parent verifier, or if this is a root verifier.
+ /// The game engine to verify against.
+ /// The settings that control the verification run.
+ /// The service provider used to resolve dependencies.
+ /// , , or is .
protected GameVerifierBase(
IGameVerifierInfo? parent,
IStarWarsGameEngine gameEngine,
@@ -74,6 +105,9 @@ protected GameVerifierBase(
VerifierChain = this.GetVerifierChain();
}
+ /// Records a verification error, raising the event the first time the error is seen.
+ /// The verification error to record.
+ /// The severity of is at least the configured throw threshold.
protected void AddError(VerificationError error)
{
if (_verifyErrors.TryAdd(error, 0))
@@ -85,6 +119,10 @@ protected void AddError(VerificationError error)
}
}
+ /// Runs the specified action, routing exceptions that match the filter to the handler.
+ /// The verification action to run.
+ /// A predicate that selects which exceptions are handled; exceptions that do not match are not caught.
+ /// The handler invoked for an exception that matches .
protected void GuardedVerify(Action action, Predicate exceptionFilter, Action exceptionHandler)
{
try
@@ -97,6 +135,9 @@ protected void GuardedVerify(Action action, Predicate exceptionFilter
}
}
+ /// Raises the event with the specified progress value and message.
+ /// The progress value, between 0.0 and 1.0.
+ /// The progress message, or if none.
protected void OnProgress(double progress, string? message)
{
Progress?.Invoke(this, new(progress, message));
diff --git a/src/ModVerify/Verifiers/IGameVerifierInfo.cs b/src/ModVerify/Verifiers/IGameVerifierInfo.cs
index 731d6056..f7049685 100644
--- a/src/ModVerify/Verifiers/IGameVerifierInfo.cs
+++ b/src/ModVerify/Verifiers/IGameVerifierInfo.cs
@@ -1,14 +1,19 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace AET.ModVerify.Verifiers;
+/// Provides identity and lineage information about a game verifier.
public interface IGameVerifierInfo
{
+ /// Gets the parent verifier that created this verifier, or if this is a root verifier.
IGameVerifierInfo? Parent { get; }
+ /// Gets the chain of verifiers from the root down to and including this verifier.
IReadOnlyList VerifierChain { get; }
+ /// Gets the unique name of the verifier.
string Name { get; }
+ /// Gets the human-readable name of the verifier.
string FriendlyName { get; }
}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/NamedGameEntityVerifier.cs b/src/ModVerify/Verifiers/NamedGameEntityVerifier.cs
index 18ec9c30..ce54e976 100644
--- a/src/ModVerify/Verifiers/NamedGameEntityVerifier.cs
+++ b/src/ModVerify/Verifiers/NamedGameEntityVerifier.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading;
using AET.ModVerify.Settings;
using AET.ModVerify.Verifiers.Commons;
@@ -9,17 +9,25 @@
namespace AET.ModVerify.Verifiers;
+/// Provides the base class for verifiers that iterate the named entities of a game manager, checking each entity and its duplicates.
+/// The type of named XML entity to verify.
+/// The game engine to verify against.
+/// The settings that control the verification run.
+/// The service provider used to resolve dependencies.
public abstract partial class NamedGameEntityVerifier(
IStarWarsGameEngine gameEngine,
GameVerifySettings settings,
- IServiceProvider serviceProvider)
+ IServiceProvider serviceProvider)
: GameVerifier(null, gameEngine, settings, serviceProvider)
where T : NamedXmlObject
{
+ /// Gets the game manager that provides the entities to verify.
public abstract IGameManager GameManager { get; }
+ /// Gets the display name of the entity type being verified.
public abstract string EntityTypeName { get; }
+ ///
public sealed override void Verify(CancellationToken token)
{
OnProgress(0.0, $"Verifying GameManager for '{EntityTypeName}'");
@@ -41,12 +49,23 @@ public sealed override void Verify(CancellationToken token)
PostEntityVerify(token);
}
+ /// Performs verification after all entities have been verified.
+ /// The token to monitor for cancellation requests.
+ /// The default implementation does nothing.
protected virtual void PostEntityVerify(CancellationToken token)
{
}
+ /// Verifies a single entity.
+ /// The entity to verify.
+ /// The context entries describing the entity, used for error reporting.
+ /// The current progress value, between 0.0 and 1.0.
+ /// The token to monitor for cancellation requests.
protected abstract void VerifyEntity(T entity, string[] context, double progress, CancellationToken token);
+ /// Performs verification before any entity is verified.
+ /// The token to monitor for cancellation requests.
+ /// The default implementation checks the game manager for duplicate entries.
protected virtual void PreEntityVerify(CancellationToken token)
{
VerifyDuplicates(token);
diff --git a/src/ModVerify/Verifiers/Utilities/DuplicateVerificationContextExtensions.cs b/src/ModVerify/Verifiers/Utilities/DuplicateVerificationContextExtensions.cs
index cd81de69..b1c2f74a 100644
--- a/src/ModVerify/Verifiers/Utilities/DuplicateVerificationContextExtensions.cs
+++ b/src/ModVerify/Verifiers/Utilities/DuplicateVerificationContextExtensions.cs
@@ -1,20 +1,30 @@
-using AET.ModVerify.Verifiers.Commons;
+using AET.ModVerify.Verifiers.Commons;
using PG.StarWarsGame.Engine;
using PG.StarWarsGame.Files.MTD.Files;
using PG.StarWarsGame.Files.XML.Data;
namespace AET.ModVerify.Verifiers.Utilities;
+/// Provides factory methods for creating instances.
public static class DuplicateVerificationContextExtensions
{
extension(IDuplicateVerificationContext)
{
+ /// Creates a duplicate verification context for the entries of an MTD file.
+ /// The MTD file whose entries are checked for duplicates.
+ /// A new duplicate verification context.
public static IDuplicateVerificationContext CreateForMtd(IMtdFile mtdFile)
{
return new MtdDuplicateVerificationContext(mtdFile);
}
- public static IDuplicateVerificationContext CreateForNamedXmlObjects(IGameManager gameManager, string databaseName) where T : NamedXmlObject
+ /// Creates a duplicate verification context for the named entities of a game manager.
+ /// The type of named XML entity.
+ /// The game manager whose entities are checked for duplicates.
+ /// The name of the database, used for error reporting.
+ /// A new duplicate verification context.
+ public static IDuplicateVerificationContext CreateForNamedXmlObjects(IGameManager gameManager, string databaseName)
+ where T : NamedXmlObject
{
return new NamedXmlObjectDuplicateVerificationContext(databaseName, gameManager);
}
diff --git a/src/ModVerify/Verifiers/VerificationErrorEventArgs.cs b/src/ModVerify/Verifiers/VerificationErrorEventArgs.cs
index dcb85666..9891c882 100644
--- a/src/ModVerify/Verifiers/VerificationErrorEventArgs.cs
+++ b/src/ModVerify/Verifiers/VerificationErrorEventArgs.cs
@@ -1,9 +1,13 @@
-using System;
+using System;
using AET.ModVerify.Reporting;
namespace AET.ModVerify.Verifiers;
+/// Provides data for the event raised when a verifier reports a verification error.
+/// The verification error that was reported.
+/// is .
public sealed class VerificationErrorEventArgs(VerificationError error) : EventArgs
{
+ /// Gets the verification error that was reported.
public VerificationError Error { get; } = error ?? throw new ArgumentNullException(nameof(error));
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine.FileSystem.Test/PG.StarWarsGame.Engine.FileSystem.Test.csproj b/src/PetroglyphTools/PG.StarWarsGame.Engine.FileSystem.Test/PG.StarWarsGame.Engine.FileSystem.Test.csproj
index 3b616cdd..8bc56ecb 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine.FileSystem.Test/PG.StarWarsGame.Engine.FileSystem.Test.csproj
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine.FileSystem.Test/PG.StarWarsGame.Engine.FileSystem.Test.csproj
@@ -18,7 +18,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine.Test/PG.StarWarsGame.Engine.Test.csproj b/src/PetroglyphTools/PG.StarWarsGame.Engine.Test/PG.StarWarsGame.Engine.Test.csproj
index 059819a0..1d746d3e 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine.Test/PG.StarWarsGame.Engine.Test.csproj
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine.Test/PG.StarWarsGame.Engine.Test.csproj
@@ -19,7 +19,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj b/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj
index ff2021d5..ec09fa28 100644
--- a/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj
+++ b/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj
@@ -20,7 +20,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/ModVerify.Test/ModVerify.Test.csproj b/test/ModVerify.Test/ModVerify.Test.csproj
index 44a43c31..d3dce840 100644
--- a/test/ModVerify.Test/ModVerify.Test.csproj
+++ b/test/ModVerify.Test/ModVerify.Test.csproj
@@ -19,7 +19,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/ModVerify.Test/Reporting/SuppressionListTest.cs b/test/ModVerify.Test/Reporting/SuppressionListTest.cs
new file mode 100644
index 00000000..b6d9363b
--- /dev/null
+++ b/test/ModVerify.Test/Reporting/SuppressionListTest.cs
@@ -0,0 +1,52 @@
+using System.Collections.Generic;
+using AET.ModVerify.Reporting;
+using AET.ModVerify.Reporting.Suppressions;
+using AET.ModVerify.Verifiers;
+using Xunit;
+
+namespace ModVerify.Test.Reporting;
+
+public class SuppressionListTest
+{
+ [Fact]
+ public void Suppresses_ErrorMatchedOnlyByDisjointFilter_IsStillSuppressed()
+ {
+ var list = new SuppressionList(
+ [
+ new SuppressionFilter(id: "E1", verifier: null, asset: null),
+ new SuppressionFilter(id: null, verifier: "V", asset: "a"),
+ ]);
+
+ // Matches only the second filter (Verifier "V" + Asset "a"); the first (Id "E1") does not apply.
+ var error = CreateError(id: "OTHER", verifier: "V", asset: "a");
+
+ Assert.True(list.Suppresses(error));
+ }
+
+ [Fact]
+ public void Suppresses_ErrorMatchedByBroadFilter_IsSuppressed()
+ {
+ var list = new SuppressionList(
+ [
+ new SuppressionFilter(id: "E1", verifier: null, asset: null),
+ new SuppressionFilter(id: null, verifier: "V", asset: "a"),
+ ]);
+
+ var error = CreateError(id: "E1", verifier: "AnyVerifier", asset: "any-asset");
+
+ Assert.True(list.Suppresses(error));
+ }
+
+ private static VerificationError CreateError(string id, string verifier, string asset)
+ {
+ return new VerificationError(id, "message", new FakeVerifierInfo(verifier), ["ctx"], asset, VerificationSeverity.Warning);
+ }
+
+ private sealed class FakeVerifierInfo(string name) : IGameVerifierInfo
+ {
+ public IGameVerifierInfo? Parent => null;
+ public IReadOnlyList VerifierChain => [this];
+ public string Name { get; } = name;
+ public string FriendlyName => Name;
+ }
+}