]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Make YAML Linter validate server/client-only components (#26809)
authorTayrtahn <tayrtahn@gmail.com>
Fri, 19 Apr 2024 17:28:33 +0000 (13:28 -0400)
committerGitHub <noreply@github.com>
Fri, 19 Apr 2024 17:28:33 +0000 (13:28 -0400)
* 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>
Content.YAMLLinter/Program.cs
Resources/Prototypes/Hydroponics/seeds.yml
Resources/Prototypes/Reagents/toxins.yml

index b7b70bd1188c643eff61ffb7faa20064b4508bd1..b23faa48fcd0c066a0c62c954d547f527929db58 100644 (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();
+            }
+        }
     }
 }
index 8bbbed6135f29bcfd8712f5570e4ed178600422d..472242a5c3ea36d48bf2953b585c9edad7636443 100644 (file)
   nutrientConsumption: 0.70
   idealLight: 8
   idealHeat: 298
-  juicy: true
   growthStages: 2
   splatPrototype: PuddleSplatter
   chemicals:
index 11a9fd00aed84ce33811c297486dde5cb50afdaf..8c91c5f226f032a028fb7d9ba14aed30f87110a0 100644 (file)
           - !type:OrganType
             type: Animal
             shouldHave: false
-        reagent: Protein
         type: Local
         visualType: MediumCaution
         messages: [ "generic-reagent-effect-sick" ]