From 299da35c8758c408f2333d825a3e3c1243a87b6f Mon Sep 17 00:00:00 2001 From: Tayrtahn Date: Fri, 19 Apr 2024 13:28:33 -0400 Subject: [PATCH] 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 --- Content.YAMLLinter/Program.cs | 46 +++++++++++++++++++++- Resources/Prototypes/Hydroponics/seeds.yml | 1 - Resources/Prototypes/Reagents/toxins.yml | 1 - 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Content.YAMLLinter/Program.cs b/Content.YAMLLinter/Program.cs index b7b70bd118..b23faa48fc 100644 --- a/Content.YAMLLinter/Program.cs +++ b/Content.YAMLLinter/Program.cs @@ -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> YamlErrors , List FieldErrors)> + public static async Task<(Dictionary> YamlErrors, List 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>(); 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(); + return refl.Assemblies.ToArray(); + } + } } } diff --git a/Resources/Prototypes/Hydroponics/seeds.yml b/Resources/Prototypes/Hydroponics/seeds.yml index 8bbbed6135..472242a5c3 100644 --- a/Resources/Prototypes/Hydroponics/seeds.yml +++ b/Resources/Prototypes/Hydroponics/seeds.yml @@ -521,7 +521,6 @@ nutrientConsumption: 0.70 idealLight: 8 idealHeat: 298 - juicy: true growthStages: 2 splatPrototype: PuddleSplatter chemicals: diff --git a/Resources/Prototypes/Reagents/toxins.yml b/Resources/Prototypes/Reagents/toxins.yml index 11a9fd00ae..8c91c5f226 100644 --- a/Resources/Prototypes/Reagents/toxins.yml +++ b/Resources/Prototypes/Reagents/toxins.yml @@ -481,7 +481,6 @@ - !type:OrganType type: Animal shouldHave: false - reagent: Protein type: Local visualType: MediumCaution messages: [ "generic-reagent-effect-sick" ]