Merge pull request #8936 from Mailaender/lint-perf
Improved the --check-yaml performance
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -20,24 +21,29 @@ namespace OpenRA.Mods.Common.Lint
|
||||
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
if (map != null && !map.RuleDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
this.emitError = emitError;
|
||||
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
foreach (var traitInfo in actorInfo.Value.Traits.WithInterface<ITraitInfo>())
|
||||
CheckTrait(actorInfo.Value, traitInfo, map);
|
||||
CheckTrait(actorInfo.Value, traitInfo, rules);
|
||||
}
|
||||
|
||||
void CheckTrait(ActorInfo actorInfo, ITraitInfo traitInfo, Map map)
|
||||
void CheckTrait(ActorInfo actorInfo, ITraitInfo traitInfo, Ruleset rules)
|
||||
{
|
||||
var actualType = traitInfo.GetType();
|
||||
foreach (var field in actualType.GetFields())
|
||||
{
|
||||
if (field.HasAttribute<ActorReferenceAttribute>())
|
||||
CheckReference(actorInfo, traitInfo, field, map.Rules.Actors, "actor");
|
||||
CheckReference(actorInfo, traitInfo, field, rules.Actors, "actor");
|
||||
if (field.HasAttribute<WeaponReferenceAttribute>())
|
||||
CheckReference(actorInfo, traitInfo, field, map.Rules.Weapons, "weapon");
|
||||
CheckReference(actorInfo, traitInfo, field, rules.Weapons, "weapon");
|
||||
if (field.HasAttribute<VoiceSetReferenceAttribute>())
|
||||
CheckReference(actorInfo, traitInfo, field, map.Rules.Voices, "voice");
|
||||
CheckReference(actorInfo, traitInfo, field, rules.Voices, "voice");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
var actorTypes = map.ActorDefinitions.Select(a => a.Value.Value);
|
||||
foreach (var actor in actorTypes)
|
||||
if (!map.Rules.Actors.Keys.Contains(actor.ToLowerInvariant()))
|
||||
|
||||
@@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
if (map != null && !map.RuleDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
var animations = actorInfo.Value.Traits.WithInterface<WithDeathAnimationInfo>().ToList();
|
||||
if (!animations.Any())
|
||||
@@ -34,7 +39,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
if (!targetable.Any())
|
||||
continue;
|
||||
|
||||
foreach (var weaponInfo in map.Rules.Weapons)
|
||||
foreach (var weaponInfo in rules.Weapons)
|
||||
{
|
||||
var warheads = weaponInfo.Value.Warheads.OfType<DamageWarhead>().Where(dw => dw.Damage > 0);
|
||||
|
||||
|
||||
@@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
if (map != null && !map.RuleDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
if (actorInfo.Key.StartsWith("^"))
|
||||
continue;
|
||||
|
||||
@@ -18,6 +18,9 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
if (map.Bounds.Left == 0 || map.Bounds.Top == 0
|
||||
|| map.Bounds.Right == map.MapSize.X || map.Bounds.Bottom == map.MapSize.Y)
|
||||
emitError("This map does not define a valid cordon.\n"
|
||||
|
||||
@@ -19,6 +19,9 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
var players = new MapPlayers(map.PlayerDefinitions).Players;
|
||||
|
||||
var playerNames = players.Values.Select(p => p.Name).ToHashSet();
|
||||
|
||||
@@ -20,7 +20,12 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
if (map != null && !map.RuleDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
if (actorInfo.Key.StartsWith("^"))
|
||||
continue;
|
||||
|
||||
@@ -26,23 +26,32 @@ namespace OpenRA.Mods.Common.Lint
|
||||
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
if (map != null && !map.SequenceDefinitions.Any())
|
||||
return;
|
||||
|
||||
this.emitWarning = emitWarning;
|
||||
|
||||
sequenceDefinitions = MiniYaml.MergeLiberal(map.SequenceDefinitions,
|
||||
var sequenceSource = map != null ? map.SequenceDefinitions : new List<MiniYamlNode>();
|
||||
sequenceDefinitions = MiniYaml.MergeLiberal(sequenceSource,
|
||||
Game.ModData.Manifest.Sequences.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal));
|
||||
|
||||
var races = map.Rules.Actors["world"].Traits.WithInterface<FactionInfo>().Select(f => f.InternalName).ToArray();
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
var races = rules.Actors["world"].Traits.WithInterface<FactionInfo>().Select(f => f.InternalName).ToArray();
|
||||
var sequenceProviders = map == null ? rules.Sequences.Values : new[] { rules.Sequences[map.Tileset] };
|
||||
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
foreach (var renderInfo in actorInfo.Value.Traits.WithInterface<RenderSpritesInfo>())
|
||||
{
|
||||
foreach (var race in races)
|
||||
{
|
||||
var image = renderInfo.GetImage(actorInfo.Value, map.Rules.Sequences[map.Tileset], race);
|
||||
if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^"))
|
||||
emitWarning("Sprite image {0} from actor {1} on tileset {2} using race {3} has no sequence definition."
|
||||
foreach (var sequenceProvider in sequenceProviders)
|
||||
{
|
||||
var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, race);
|
||||
if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^"))
|
||||
emitWarning("Sprite image {0} from actor {1} on tileset {2} using race {3} has no sequence definition."
|
||||
.F(image, actorInfo.Value.Name, map.Tileset, race));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +91,11 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
else
|
||||
{
|
||||
var image = renderInfo.GetImage(actorInfo.Value, map.SequenceProvider, race);
|
||||
CheckDefintions(image, sequenceReference, actorInfo, sequence, race, field, traitInfo);
|
||||
foreach (var sequenceProvider in sequenceProviders)
|
||||
{
|
||||
var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, race);
|
||||
CheckDefintions(image, sequenceReference, actorInfo, sequence, race, field, traitInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,7 +103,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var weaponInfo in map.Rules.Weapons)
|
||||
foreach (var weaponInfo in rules.Weapons)
|
||||
{
|
||||
var projectileInfo = weaponInfo.Value.Projectile;
|
||||
if (projectileInfo == null)
|
||||
|
||||
@@ -19,6 +19,9 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
if (map != null)
|
||||
return;
|
||||
|
||||
/* first, check all the types implementing ISync */
|
||||
foreach (var t in Game.ModData.ObjectCreator.GetTypesImplementing<ISync>())
|
||||
if (!HasAnySyncFields(t))
|
||||
|
||||
@@ -18,7 +18,12 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
foreach (var actorInfo in map.Rules.Actors.Where(a => !a.Key.StartsWith("^")))
|
||||
if (map != null && !map.RuleDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
foreach (var actorInfo in rules.Actors.Where(a => !a.Key.StartsWith("^")))
|
||||
try
|
||||
{
|
||||
var hasTraits = actorInfo.Value.TraitsInConstructOrder().Any();
|
||||
|
||||
@@ -20,15 +20,20 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
CheckUpgradesValidity(emitError, map);
|
||||
CheckUpgradesUsage(emitError, emitWarning, map);
|
||||
if (map != null && !map.RuleDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
CheckUpgradesValidity(emitError, rules);
|
||||
CheckUpgradesUsage(emitError, emitWarning, rules);
|
||||
}
|
||||
|
||||
private static void CheckUpgradesValidity(Action<string> emitError, Map map)
|
||||
static void CheckUpgradesValidity(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
var upgradesGranted = GetAllGrantedUpgrades(emitError, map).ToHashSet();
|
||||
var upgradesGranted = GetAllGrantedUpgrades(emitError, rules).ToHashSet();
|
||||
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
foreach (var trait in actorInfo.Value.Traits)
|
||||
{
|
||||
@@ -43,12 +48,12 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckUpgradesUsage(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
static void CheckUpgradesUsage(Action<string> emitError, Action<string> emitWarning, Ruleset rules)
|
||||
{
|
||||
var upgradesUsed = GetAllUsedUpgrades(emitError, map).ToHashSet();
|
||||
var upgradesUsed = GetAllUsedUpgrades(emitError, rules).ToHashSet();
|
||||
|
||||
// Check all upgrades granted by traits.
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
foreach (var trait in actorInfo.Value.Traits)
|
||||
{
|
||||
@@ -63,7 +68,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
|
||||
// Check all upgrades granted by warheads.
|
||||
foreach (var weapon in map.Rules.Weapons)
|
||||
foreach (var weapon in rules.Weapons)
|
||||
{
|
||||
foreach (var warhead in weapon.Value.Warheads)
|
||||
{
|
||||
@@ -78,10 +83,10 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<string> GetAllGrantedUpgrades(Action<string> emitError, Map map)
|
||||
static IEnumerable<string> GetAllGrantedUpgrades(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
// Get all upgrades granted by traits.
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
foreach (var trait in actorInfo.Value.Traits)
|
||||
{
|
||||
@@ -96,7 +101,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
|
||||
// Get all upgrades granted by warheads.
|
||||
foreach (var weapon in map.Rules.Weapons)
|
||||
foreach (var weapon in rules.Weapons)
|
||||
{
|
||||
foreach (var warhead in weapon.Value.Warheads)
|
||||
{
|
||||
@@ -111,23 +116,23 @@ namespace OpenRA.Mods.Common.Lint
|
||||
}
|
||||
|
||||
// TODO: HACK because GainsExperience grants upgrades differently to most other sources.
|
||||
var gainsExperience = map.Rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<GainsExperienceInfo>()
|
||||
var gainsExperience = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<GainsExperienceInfo>()
|
||||
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
|
||||
|
||||
foreach (var upgrade in gainsExperience)
|
||||
yield return upgrade;
|
||||
|
||||
// TODO: HACK because Pluggable grants upgrades differently to most other sources.
|
||||
var pluggable = map.Rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<PluggableInfo>()
|
||||
var pluggable = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<PluggableInfo>()
|
||||
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
|
||||
|
||||
foreach (var upgrade in pluggable)
|
||||
yield return upgrade;
|
||||
}
|
||||
|
||||
static IEnumerable<string> GetAllUsedUpgrades(Action<string> emitError, Map map)
|
||||
static IEnumerable<string> GetAllUsedUpgrades(Action<string> emitError, Ruleset rules)
|
||||
{
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
foreach (var trait in actorInfo.Value.Traits)
|
||||
{
|
||||
@@ -143,7 +148,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
|
||||
// TODO: HACK because GainsExperience and GainsStatUpgrades do not play by the rules...
|
||||
// We assume everything GainsExperience grants is used by GainsStatUpgrade
|
||||
var gainsExperience = map.Rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<GainsExperienceInfo>()
|
||||
var gainsExperience = rules.Actors.SelectMany(x => x.Value.Traits.WithInterface<GainsExperienceInfo>()
|
||||
.SelectMany(y => y.Upgrades.SelectMany(z => z.Value)));
|
||||
|
||||
foreach (var upgrade in gainsExperience)
|
||||
|
||||
@@ -19,7 +19,12 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
foreach (var actorInfo in map.Rules.Actors)
|
||||
if (map != null && !map.RuleDefinitions.Any() && !map.VoiceDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
foreach (var actorInfo in rules.Actors)
|
||||
{
|
||||
foreach (var traitInfo in actorInfo.Value.Traits.WithInterface<ITraitInfo>())
|
||||
{
|
||||
@@ -32,16 +37,16 @@ namespace OpenRA.Mods.Common.Lint
|
||||
if (string.IsNullOrEmpty(voiceSet))
|
||||
continue;
|
||||
|
||||
CheckVoices(actorInfo.Value, emitError, map, voiceSet);
|
||||
CheckVoices(actorInfo.Value, emitError, rules, voiceSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckVoices(ActorInfo actorInfo, Action<string> emitError, Map map, string voiceSet)
|
||||
void CheckVoices(ActorInfo actorInfo, Action<string> emitError, Ruleset rules, string voiceSet)
|
||||
{
|
||||
var soundInfo = map.Rules.Voices[voiceSet.ToLowerInvariant()];
|
||||
var soundInfo = rules.Voices[voiceSet.ToLowerInvariant()];
|
||||
|
||||
foreach (var traitInfo in actorInfo.Traits.WithInterface<ITraitInfo>())
|
||||
{
|
||||
|
||||
@@ -19,20 +19,25 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
|
||||
{
|
||||
if (map != null && !map.RuleDefinitions.Any())
|
||||
return;
|
||||
|
||||
var rules = map == null ? Game.ModData.DefaultRules : map.Rules;
|
||||
|
||||
// ProvidesPrerequisite allows arbitrary prereq definitions
|
||||
var customPrereqs = map.Rules.Actors.SelectMany(a => a.Value.Traits
|
||||
var customPrereqs = rules.Actors.SelectMany(a => a.Value.Traits
|
||||
.WithInterface<ProvidesPrerequisiteInfo>().Select(p => p.Prerequisite ?? a.Value.Name));
|
||||
|
||||
// ProvidesTechPrerequisite allows arbitrary prereq definitions
|
||||
// (but only one group at a time during gameplay)
|
||||
var techPrereqs = map.Rules.Actors.SelectMany(a => a.Value.Traits
|
||||
var techPrereqs = rules.Actors.SelectMany(a => a.Value.Traits
|
||||
.WithInterface<ProvidesTechPrerequisiteInfo>())
|
||||
.SelectMany(p => p.Prerequisites);
|
||||
|
||||
var providedPrereqs = customPrereqs.Concat(techPrereqs);
|
||||
|
||||
// TODO: this check is case insensitive while the real check in-game is not
|
||||
foreach (var i in map.Rules.Actors)
|
||||
foreach (var i in rules.Actors)
|
||||
{
|
||||
var bi = i.Value.Traits.GetOrDefault<BuildableInfo>();
|
||||
if (bi != null)
|
||||
|
||||
@@ -49,21 +49,29 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
ObjectCreator.MissingTypeAction = s => EmitError("Missing Type: {0}".F(s));
|
||||
FieldLoader.UnknownFieldAction = (s, f) => EmitError("FieldLoader: Missing field `{0}` on `{1}`".F(s, f.Name));
|
||||
|
||||
IEnumerable<Map> maps;
|
||||
var maps = new List<Map>();
|
||||
if (args.Length < 2)
|
||||
{
|
||||
maps.Add(null);
|
||||
Game.ModData.MapCache.LoadMaps();
|
||||
maps = Game.ModData.MapCache
|
||||
maps.AddRange(Game.ModData.MapCache
|
||||
.Where(m => m.Status == MapStatus.Available)
|
||||
.Select(m => m.Map);
|
||||
.Select(m => m.Map));
|
||||
}
|
||||
else
|
||||
maps = new[] { new Map(args[1]) };
|
||||
maps.Add(new Map(args[1]));
|
||||
|
||||
foreach (var testMap in maps)
|
||||
{
|
||||
Console.WriteLine("Testing map: {0}".F(testMap.Title));
|
||||
testMap.PreloadRules();
|
||||
if (testMap != null)
|
||||
{
|
||||
Console.WriteLine("Testing map: {0}".F(testMap.Title));
|
||||
testMap.PreloadRules();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Testing mod: {0}".F(Game.ModData.Manifest.Mod.Title));
|
||||
}
|
||||
|
||||
foreach (var customPassType in Game.ModData.ObjectCreator
|
||||
.GetTypesImplementing<ILintPass>())
|
||||
|
||||
Reference in New Issue
Block a user