Validate prototype ids in c# fields (#18224)
This commit is contained in:
@@ -7,6 +7,7 @@ using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Markdown.Validation;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.UnitTesting;
|
||||
|
||||
namespace Content.YAMLLinter
|
||||
{
|
||||
@@ -17,9 +18,11 @@ namespace Content.YAMLLinter
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
var errors = await RunValidation();
|
||||
var (errors, fieldErrors) = await RunValidation();
|
||||
|
||||
if (errors.Count == 0)
|
||||
var count = errors.Count + fieldErrors.Count;
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
Console.WriteLine($"No errors found in {(int) stopwatch.Elapsed.TotalMilliseconds} ms.");
|
||||
return 0;
|
||||
@@ -33,80 +36,92 @@ namespace Content.YAMLLinter
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"{errors.Count} errors found in {(int) stopwatch.Elapsed.TotalMilliseconds} ms.");
|
||||
foreach (var error in fieldErrors)
|
||||
{
|
||||
Console.WriteLine(error);
|
||||
}
|
||||
|
||||
Console.WriteLine($"{count} errors found in {(int) stopwatch.Elapsed.TotalMilliseconds} ms.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static async Task<Dictionary<string, HashSet<ErrorNode>>> ValidateClient()
|
||||
private static async Task<(Dictionary<string, HashSet<ErrorNode>> YamlErrors, List<string> FieldErrors)>
|
||||
ValidateClient()
|
||||
{
|
||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings { DummyTicker = true, Disconnected = true });
|
||||
var client = pairTracker.Pair.Client;
|
||||
|
||||
var cPrototypeManager = client.ResolveDependency<IPrototypeManager>();
|
||||
var clientErrors = new Dictionary<string, HashSet<ErrorNode>>();
|
||||
|
||||
await client.WaitPost(() =>
|
||||
{
|
||||
clientErrors = cPrototypeManager.ValidateDirectory(new ResPath("/Prototypes"));
|
||||
});
|
||||
|
||||
var result = await ValidateInstance(client);
|
||||
await pairTracker.CleanReturnAsync();
|
||||
|
||||
return clientErrors;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static async Task<Dictionary<string, HashSet<ErrorNode>>> ValidateServer()
|
||||
private static async Task<(Dictionary<string, HashSet<ErrorNode>> YamlErrors, List<string> FieldErrors)>
|
||||
ValidateServer()
|
||||
{
|
||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings { DummyTicker = true, Disconnected = true });
|
||||
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings { DummyTicker = true, NoClient = true });
|
||||
var server = pairTracker.Pair.Server;
|
||||
|
||||
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var serverErrors = new Dictionary<string, HashSet<ErrorNode>>();
|
||||
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
serverErrors = sPrototypeManager.ValidateDirectory(new ResPath("/Prototypes"));
|
||||
});
|
||||
|
||||
var result = await ValidateInstance(server);
|
||||
await pairTracker.CleanReturnAsync();
|
||||
|
||||
return serverErrors;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<Dictionary<string, HashSet<ErrorNode>>> RunValidation()
|
||||
private static async Task<(Dictionary<string, HashSet<ErrorNode>>, List<string>)> ValidateInstance(
|
||||
RobustIntegrationTest.IntegrationInstance instance)
|
||||
{
|
||||
var allErrors = new Dictionary<string, HashSet<ErrorNode>>();
|
||||
var protoMan = instance.ResolveDependency<IPrototypeManager>();
|
||||
Dictionary<string, HashSet<ErrorNode>> yamlErrors = default!;
|
||||
List<string> fieldErrors = default!;
|
||||
|
||||
await instance.WaitPost(() =>
|
||||
{
|
||||
yamlErrors = protoMan.ValidateDirectory(new ResPath("/Prototypes"), out var prototypes);
|
||||
fieldErrors = protoMan.ValidateFields(prototypes);
|
||||
});
|
||||
|
||||
return (yamlErrors, fieldErrors);
|
||||
}
|
||||
|
||||
public static async Task<(Dictionary<string, HashSet<ErrorNode>> YamlErrors , List<string> FieldErrors)>
|
||||
RunValidation()
|
||||
{
|
||||
var yamlErrors = new Dictionary<string, HashSet<ErrorNode>>();
|
||||
|
||||
var serverErrors = await ValidateServer();
|
||||
var clientErrors = await ValidateClient();
|
||||
|
||||
foreach (var (key, val) in serverErrors)
|
||||
foreach (var (key, val) in serverErrors.YamlErrors)
|
||||
{
|
||||
// Include all server errors marked as always relevant
|
||||
var newErrors = val.Where(n => n.AlwaysRelevant).ToHashSet();
|
||||
|
||||
// We include sometimes-relevant errors if they exist both for the client & server
|
||||
if (clientErrors.TryGetValue(key, out var clientVal))
|
||||
if (clientErrors.Item1.TryGetValue(key, out var clientVal))
|
||||
newErrors.UnionWith(val.Intersect(clientVal));
|
||||
|
||||
if (newErrors.Count != 0)
|
||||
allErrors[key] = newErrors;
|
||||
yamlErrors[key] = newErrors;
|
||||
}
|
||||
|
||||
// Finally add any always-relevant client errors.
|
||||
foreach (var (key, val) in clientErrors)
|
||||
// Next add any always-relevant client errors.
|
||||
foreach (var (key, val) in clientErrors.YamlErrors)
|
||||
{
|
||||
var newErrors = val.Where(n => n.AlwaysRelevant).ToHashSet();
|
||||
if (newErrors.Count == 0)
|
||||
continue;
|
||||
|
||||
if (allErrors.TryGetValue(key, out var errors))
|
||||
if (yamlErrors.TryGetValue(key, out var errors))
|
||||
errors.UnionWith(val.Where(n => n.AlwaysRelevant));
|
||||
else
|
||||
allErrors[key] = newErrors;
|
||||
yamlErrors[key] = newErrors;
|
||||
}
|
||||
|
||||
return allErrors;
|
||||
// Finally, combine the prototype ID field errors.
|
||||
var fieldErrors = serverErrors.FieldErrors
|
||||
.Concat(clientErrors.FieldErrors)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
return (yamlErrors, fieldErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user