diff --git a/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs b/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs index af27b00a45..46701403e0 100644 --- a/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs +++ b/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs @@ -253,38 +253,63 @@ namespace OpenRA.Mods.Common.Lint .SelectMany(t => Utility.GetFields(t).Where(Utility.HasAttribute))); // TODO: linter does not work with LoadUsing - GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, Utility.GetFields(typeof(GameSpeed)), modData.Manifest.Get().Speeds.Values); + foreach (var speed in modData.Manifest.Get().Speeds) + GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( + usedKeys, testedFields, + Utility.GetFields(typeof(GameSpeed)), + new[] { speed.Value }, + (obj, field) => $"`GameSpeeds.Speeds.{speed.Key}.{field.Name}` in mod.yaml"); // TODO: linter does not work with LoadUsing - GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, - Utility.GetFields(typeof(ResourceRendererInfo.ResourceTypeInfo)), - modData.DefaultRules.Actors - .SelectMany(actorInfo => actorInfo.Value.TraitInfos()) - .SelectMany(info => info.ResourceTypes.Values)); + foreach (var resource in modData.DefaultRules.Actors + .SelectMany(actorInfo => actorInfo.Value.TraitInfos()) + .SelectMany(info => info.ResourceTypes)) + GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( + usedKeys, testedFields, + Utility.GetFields(typeof(ResourceRendererInfo.ResourceTypeInfo)), + new[] { resource.Value }, + (obj, field) => $"`ResourceRenderer.ResourceTypes.{resource.Key}.{field.Name}` in rules yaml"); const BindingFlags Binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; var constFields = modData.ObjectCreator.GetTypes().SelectMany(modType => modType.GetFields(Binding)).Where(f => f.IsLiteral); GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, constFields, new[] { (object)null }); + usedKeys, testedFields, + constFields, + new[] { (object)null }, + (obj, field) => $"`{field.ReflectedType.Name}.{field.Name}`"); var modMetadataFields = typeof(ModMetadata).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, modMetadataFields, new[] { modData.Manifest.Metadata }); + usedKeys, testedFields, + modMetadataFields, + new[] { modData.Manifest.Metadata }, + (obj, field) => $"`Metadata.{field.Name}` in mod.yaml"); var modContent = modData.Manifest.Get(); GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, Utility.GetFields(typeof(ModContent)), new[] { modContent }); - GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, Utility.GetFields(typeof(ModContent.ModPackage)), modContent.Packages.Values); + usedKeys, testedFields, + Utility.GetFields(typeof(ModContent)), + new[] { modContent }, + (obj, field) => $"`ModContent.{field.Name}` in mod.yaml"); + foreach (var package in modContent.Packages) + GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( + usedKeys, testedFields, + Utility.GetFields(typeof(ModContent.ModPackage)), + new[] { package.Value }, + (obj, field) => $"`ModContent.Packages.ContentPackage@{package.Key}.{field.Name}` in mod.yaml"); GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, Utility.GetFields(typeof(HotkeyDefinition)), modData.Hotkeys.Definitions); + usedKeys, testedFields, + Utility.GetFields(typeof(HotkeyDefinition)), + modData.Hotkeys.Definitions, + (obj, field) => $"`{obj.Name}.{field.Name}` in hotkeys yaml"); // All keycodes and modifiers should be marked as used, as they can all be configured for use at hotkeys at runtime. GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( - usedKeys, testedFields, Utility.GetFields(typeof(KeycodeExts)).Concat(Utility.GetFields(typeof(ModifiersExts))), new[] { (object)null }); + usedKeys, testedFields, + Utility.GetFields(typeof(KeycodeExts)).Concat(Utility.GetFields(typeof(ModifiersExts))), + new[] { (object)null }, + (obj, field) => $"`{field.ReflectedType.Name}.{field.Name}`"); foreach (var filename in modData.Manifest.ChromeLayout) CheckHotkeysSettingsLogic(usedKeys, MiniYaml.FromStream(modData.DefaultFileSystem.Open(filename), filename)); @@ -312,9 +337,10 @@ namespace OpenRA.Mods.Common.Lint return (usedKeys, testedFields); } - static void GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( + static void GetUsedTranslationKeysFromFieldsWithTranslationReferenceAttribute( Keys usedKeys, List testedFields, - IEnumerable newFields, IEnumerable objects) + IEnumerable newFields, IEnumerable objects, + Func getContext) { var fieldsWithAttribute = newFields @@ -328,7 +354,7 @@ namespace OpenRA.Mods.Common.Lint { var keys = LintExts.GetFieldValues(obj, field, fluentReference.DictionaryReference); foreach (var key in keys) - usedKeys.Add(key, fluentReference, $"`{field.ReflectedType.Name}.{field.Name}`"); + usedKeys.Add(key, fluentReference, getContext(obj, field)); } } }