Added try/catch for TypeDictionary errors in Lint code

TypeDictionary errors are very hard for modders to debug as they don't mention which actor is causing the error
This commit is contained in:
Gustas
2022-08-15 18:19:40 +03:00
committed by abcdefg30
parent cc58fe1a0f
commit d438508994
6 changed files with 135 additions and 88 deletions

View File

@@ -32,6 +32,9 @@ namespace OpenRA.Mods.Common.Lint
void Run(Action<string> emitError, Ruleset rules) void Run(Action<string> emitError, Ruleset rules)
{ {
foreach (var actorInfo in rules.Actors) foreach (var actorInfo in rules.Actors)
{
// Catch TypeDictionary errors
try
{ {
var count = actorInfo.Value.TraitInfos<IDefaultVisibilityInfo>().Count(); var count = actorInfo.Value.TraitInfos<IDefaultVisibilityInfo>().Count();
@@ -52,6 +55,11 @@ namespace OpenRA.Mods.Common.Lint
} }
} }
} }
catch (InvalidOperationException e)
{
emitError($"{e.Message} (Actor type `{actorInfo.Key}`)");
}
}
} }
} }
} }

View File

@@ -32,6 +32,9 @@ namespace OpenRA.Mods.Common.Lint
void Run(Action<string> emitError, Ruleset rules) void Run(Action<string> emitError, Ruleset rules)
{ {
foreach (var actorInfo in rules.Actors) foreach (var actorInfo in rules.Actors)
{
// Catch TypeDictionary errors
try
{ {
var health = actorInfo.Value.TraitInfoOrDefault<IHealthInfo>(); var health = actorInfo.Value.TraitInfoOrDefault<IHealthInfo>();
if (health == null) if (health == null)
@@ -41,6 +44,11 @@ namespace OpenRA.Mods.Common.Lint
if (!hitShapes.Any()) if (!hitShapes.Any())
emitError($"Actor type `{actorInfo.Key}` has a Health trait but no HitShape trait!"); emitError($"Actor type `{actorInfo.Key}` has a Health trait but no HitShape trait!");
} }
catch (InvalidOperationException e)
{
emitError($"{e.Message} (Actor type `{actorInfo.Key}`)");
}
}
} }
} }
} }

View File

@@ -31,6 +31,9 @@ namespace OpenRA.Mods.Common.Lint
void Run(Action<string> emitError, Ruleset rules) void Run(Action<string> emitError, Ruleset rules)
{ {
foreach (var actorInfo in rules.Actors) foreach (var actorInfo in rules.Actors)
{
// Catch TypeDictionary errors
try
{ {
var ios = actorInfo.Value.TraitInfoOrDefault<IOccupySpaceInfo>(); var ios = actorInfo.Value.TraitInfoOrDefault<IOccupySpaceInfo>();
foreach (var rsi in actorInfo.Value.TraitInfos<RevealsShroudInfo>()) foreach (var rsi in actorInfo.Value.TraitInfos<RevealsShroudInfo>())
@@ -44,6 +47,11 @@ namespace OpenRA.Mods.Common.Lint
emitError($"Actor type `{actorInfo.Key}` defines VisibilityType.Footprint in `{rsi.GetType()}` but does not have any footprint cells!"); emitError($"Actor type `{actorInfo.Key}` defines VisibilityType.Footprint in `{rsi.GetType()}` but does not have any footprint cells!");
} }
} }
catch (InvalidOperationException e)
{
emitError($"{e.Message} (Actor type `{actorInfo.Key}`)");
}
}
} }
} }
} }

View File

@@ -39,6 +39,9 @@ namespace OpenRA.Mods.Common.Lint
{ {
var factions = rules.Actors[SystemActors.World].TraitInfos<FactionInfo>().Select(f => f.InternalName).ToArray(); var factions = rules.Actors[SystemActors.World].TraitInfos<FactionInfo>().Select(f => f.InternalName).ToArray();
foreach (var actorInfo in rules.Actors) foreach (var actorInfo in rules.Actors)
{
// Catch TypeDictionary errors
try
{ {
var images = new HashSet<string>(); var images = new HashSet<string>();
@@ -103,6 +106,11 @@ namespace OpenRA.Mods.Common.Lint
} }
} }
} }
catch (InvalidOperationException e)
{
emitError($"{e.Message} (Actor type `{actorInfo.Key}`)");
}
}
foreach (var weaponInfo in rules.Weapons) foreach (var weaponInfo in rules.Weapons)
{ {

View File

@@ -31,6 +31,9 @@ namespace OpenRA.Mods.Common.Lint
void Run(Action<string> emitError, Ruleset rules) void Run(Action<string> emitError, Ruleset rules)
{ {
foreach (var actorInfo in rules.Actors) foreach (var actorInfo in rules.Actors)
{
// Catch TypeDictionary errors
try
{ {
var buildable = actorInfo.Value.TraitInfoOrDefault<BuildableInfo>(); var buildable = actorInfo.Value.TraitInfoOrDefault<BuildableInfo>();
if (buildable == null) if (buildable == null)
@@ -40,6 +43,11 @@ namespace OpenRA.Mods.Common.Lint
if (tooltip == null) if (tooltip == null)
emitError("The following buildable actor has no (enabled) Tooltip: " + actorInfo.Key); emitError("The following buildable actor has no (enabled) Tooltip: " + actorInfo.Key);
} }
catch (InvalidOperationException e)
{
emitError($"{e.Message} (Actor type `{actorInfo.Key}`)");
}
}
} }
} }
} }

View File

@@ -33,14 +33,21 @@ namespace OpenRA.Mods.Common.Lint
var providedPrereqs = rules.Actors.SelectMany(a => a.Value.TraitInfos<ITechTreePrerequisiteInfo>().SelectMany(p => p.Prerequisites(a.Value))); var providedPrereqs = rules.Actors.SelectMany(a => a.Value.TraitInfos<ITechTreePrerequisiteInfo>().SelectMany(p => p.Prerequisites(a.Value)));
// TODO: this check is case insensitive while the real check in-game is not // TODO: this check is case insensitive while the real check in-game is not
foreach (var i in rules.Actors) foreach (var actorInfo in rules.Actors)
{ {
var bi = i.Value.TraitInfoOrDefault<BuildableInfo>(); // Catch TypeDictionary errors
try
{
var bi = actorInfo.Value.TraitInfoOrDefault<BuildableInfo>();
if (bi != null) if (bi != null)
foreach (var prereq in bi.Prerequisites) foreach (var prereq in bi.Prerequisites)
if (!prereq.StartsWith("~disabled")) if (!prereq.StartsWith("~disabled") && !providedPrereqs.Contains(prereq.Replace("!", "").Replace("~", "")))
if (!providedPrereqs.Contains(prereq.Replace("!", "").Replace("~", ""))) emitError($"Buildable actor {actorInfo.Key} has prereq {prereq} not provided by anything.");
emitError($"Buildable actor {i.Key} has prereq {prereq} not provided by anything."); }
catch (InvalidOperationException e)
{
emitError($"{e.Message} (Actor type `{actorInfo.Key}`)");
}
} }
} }
} }