Make YAML Linter validate server/client-only components (#26809)

* YAML Linter now validates invalid fields in server-only and client-only components

* Update to change in engine PR

* Use reflection manager to get the lists of client/server assemblies.

Also made it use a hashset on type instead of the previous code.

* I'm dumb my bad.

* Fix 2 errors that snuck through, showing why we need this.

---------

Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
This commit is contained in:
Tayrtahn
2024-04-19 13:28:33 -04:00
committed by GitHub
parent 5b62724de0
commit 299da35c87
3 changed files with 44 additions and 4 deletions

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Content.IntegrationTests;
using Robust.Shared.Prototypes;
using Robust.Shared.Reflection;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
@@ -103,9 +105,13 @@ namespace Content.YAMLLinter
return (yamlErrors, fieldErrors);
}
public static async Task<(Dictionary<string, HashSet<ErrorNode>> YamlErrors , List<string> FieldErrors)>
public static async Task<(Dictionary<string, HashSet<ErrorNode>> YamlErrors, List<string> FieldErrors)>
RunValidation()
{
var (clientAssemblies, serverAssemblies) = await GetClientServerAssemblies();
var serverTypes = serverAssemblies.SelectMany(n => n.GetTypes()).Select(t => t.Name).ToHashSet();
var clientTypes = clientAssemblies.SelectMany(n => n.GetTypes()).Select(t => t.Name).ToHashSet();
var yamlErrors = new Dictionary<string, HashSet<ErrorNode>>();
var serverErrors = await ValidateServer();
@@ -117,9 +123,18 @@ namespace Content.YAMLLinter
var newErrors = val.Where(n => n.AlwaysRelevant).ToHashSet();
// We include sometimes-relevant errors if they exist both for the client & server
if (clientErrors.Item1.TryGetValue(key, out var clientVal))
if (clientErrors.YamlErrors.TryGetValue(key, out var clientVal))
newErrors.UnionWith(val.Intersect(clientVal));
// Include any errors that relate to server-only types
foreach (var errorNode in val)
{
if (errorNode is FieldNotFoundErrorNode fieldNotFoundNode && !clientTypes.Contains(fieldNotFoundNode.FieldType.Name))
{
newErrors.Add(errorNode);
}
}
if (newErrors.Count != 0)
yamlErrors[key] = newErrors;
}
@@ -135,6 +150,15 @@ namespace Content.YAMLLinter
errors.UnionWith(val.Where(n => n.AlwaysRelevant));
else
yamlErrors[key] = newErrors;
// Include any errors that relate to client-only types
foreach (var errorNode in val)
{
if (errorNode is FieldNotFoundErrorNode fieldNotFoundNode && !serverTypes.Contains(fieldNotFoundNode.FieldType.Name))
{
newErrors.Add(errorNode);
}
}
}
// Finally, combine the prototype ID field errors.
@@ -145,5 +169,23 @@ namespace Content.YAMLLinter
return (yamlErrors, fieldErrors);
}
private static async Task<(Assembly[] clientAssemblies, Assembly[] serverAssemblies)>
GetClientServerAssemblies()
{
await using var pair = await PoolManager.GetServerClient();
var result = (GetAssemblies(pair.Client), GetAssemblies(pair.Server));
await pair.CleanReturnAsync();
return result;
Assembly[] GetAssemblies(RobustIntegrationTest.IntegrationInstance instance)
{
var refl = instance.ResolveDependency<IReflectionManager>();
return refl.Assemblies.ToArray();
}
}
}
}

View File

@@ -521,7 +521,6 @@
nutrientConsumption: 0.70
idealLight: 8
idealHeat: 298
juicy: true
growthStages: 2
splatPrototype: PuddleSplatter
chemicals:

View File

@@ -481,7 +481,6 @@
- !type:OrganType
type: Animal
shouldHave: false
reagent: Protein
type: Local
visualType: MediumCaution
messages: [ "generic-reagent-effect-sick" ]