Moves Lint checks to Mods.Common

This commit is contained in:
reaperrr
2015-01-15 23:15:51 +01:00
parent e82b2ce8dd
commit 52dd8c922f
11 changed files with 18 additions and 19 deletions

View File

@@ -1,68 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Reflection;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CheckActorReferences : ILintPass
{
Action<string> emitError;
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
this.emitError = emitError;
foreach (var actorInfo in map.Rules.Actors)
foreach (var traitInfo in actorInfo.Value.Traits.WithInterface<ITraitInfo>())
CheckTrait(actorInfo.Value, traitInfo, map);
}
void CheckTrait(ActorInfo actorInfo, ITraitInfo traitInfo, Map map)
{
var actualType = traitInfo.GetType();
foreach (var field in actualType.GetFields())
{
if (field.HasAttribute<ActorReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, map.Rules.Actors, "actor");
if (field.HasAttribute<WeaponReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, map.Rules.Weapons, "weapon");
if (field.HasAttribute<VoiceReferenceAttribute>())
CheckReference(actorInfo, traitInfo, field, map.Rules.Voices, "voice");
}
}
string[] GetFieldValues(ITraitInfo traitInfo, FieldInfo fieldInfo)
{
var type = fieldInfo.FieldType;
if (type == typeof(string))
return new string[] { (string)fieldInfo.GetValue(traitInfo) };
if (type == typeof(string[]))
return (string[])fieldInfo.GetValue(traitInfo);
emitError("Bad type for reference on {0}.{1}. Supported types: string, string[]"
.F(traitInfo.GetType().Name, fieldInfo.Name));
return new string[] { };
}
void CheckReference<T>(ActorInfo actorInfo, ITraitInfo traitInfo, FieldInfo fieldInfo,
IReadOnlyDictionary<string, T> dict, string type)
{
var values = GetFieldValues(traitInfo, fieldInfo);
foreach (var v in values)
if (v != null && !dict.ContainsKey(v.ToLowerInvariant()))
emitError("{0}.{1}.{2}: Missing {3} `{4}`."
.F(actorInfo.Name, traitInfo.GetType().Name, fieldInfo.Name, type, v));
}
}
}

View File

@@ -1,27 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CheckActors : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
var actorTypes = map.Actors.Value.Values.Select(a => a.Type);
foreach (var actor in actorTypes)
if (!map.Rules.Actors.Keys.Contains(actor.ToLowerInvariant()))
emitError("Actor {0} is not defined by any rule.".F(actor));
}
}
}

View File

@@ -1,28 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CheckMapCordon : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
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"
+ "A one cell (or greater) border is required on all four sides "
+ "between the playable bounds and the map edges");
}
}
}

View File

@@ -1,30 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CheckMapRules : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
try
{
Game.ModData.RulesetCache.LoadMapRules(map);
}
catch (Exception e)
{
emitError(e.Message);
}
}
}
}

View File

@@ -1,38 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CheckPlayers : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
var playerNames = map.Players.Values.Select(p => p.Name);
foreach (var player in map.Players)
foreach (var ally in player.Value.Allies)
if (!playerNames.Contains(ally))
emitError("Allies contains player {0} that is not in list.".F(ally));
foreach (var player in map.Players)
foreach (var enemy in player.Value.Enemies)
if (!playerNames.Contains(enemy))
emitError("Enemies contains player {0} that is not in list.".F(enemy));
var races = map.Rules.Actors["world"].Traits.WithInterface<CountryInfo>().Select(c => c.Race);
foreach (var player in map.Players)
if (!string.IsNullOrWhiteSpace(player.Value.Race) && player.Value.Race != "Random" && !races.Contains(player.Value.Race))
emitError("Invalid race {0} chosen for player {1}.".F(player.Value.Race, player.Value.Name));
}
}
}

View File

@@ -1,33 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class CheckSequences : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
var sequences = MiniYaml.MergeLiberal(map.SequenceDefinitions, Game.ModData.Manifest.Sequences.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal));
foreach (var actorInfo in map.Rules.Actors)
foreach (var renderInfo in actorInfo.Value.Traits.WithInterface<RenderSimpleInfo>())
{
var image = renderInfo.Image ?? actorInfo.Value.Name;
if (!sequences.Any(s => s.Key == image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^"))
emitWarning("Sprite image {0} from actor {1} has no sequence definition.".F(image, actorInfo.Value.Name));
}
}
}
}

View File

@@ -1,41 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using System.Reflection;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class CheckSyncAnnotations : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
/* first, check all the types implementing ISync */
foreach (var t in Game.ModData.ObjectCreator.GetTypesImplementing<ISync>())
if (!HasAnySyncFields(t))
emitWarning("{0} has ISync but nothing marked with [Sync]".F(t.Name));
}
bool HasAnySyncFields(Type t)
{
var flags = BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Instance;
var fs = t.GetFields(flags);
var ps = t.GetProperties(flags);
return fs.Any(f => f.HasAttribute<SyncAttribute>()) ||
ps.Any(p => p.HasAttribute<SyncAttribute>()) ||
HasAnySyncFields(t.BaseType);
}
}
}

View File

@@ -1,34 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CheckTraitPrerequisites : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
foreach (var actorInfo in map.Rules.Actors.Where(a => !a.Key.StartsWith("^")))
try
{
var traits = actorInfo.Value.TraitsInConstructOrder().ToArray();
if (traits.Length == 0)
emitWarning("Actor {0} has no traits. Is this intended?".F(actorInfo.Key));
}
catch (Exception e)
{
emitError("Actor {0} is not constructible; failure: {1}".F(actorInfo.Key, e.Message));
}
}
}
}

View File

@@ -1,52 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Mods.RA.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class LintBuildablePrerequisites : ILintPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, Map map)
{
// Buildings provide their actor names as a prerequisite
var buildingPrereqs = map.Rules.Actors.Where(a => a.Value.Traits.Contains<BuildingInfo>())
.Select(a => a.Key);
// ProvidesCustomPrerequisite allows arbitrary prereq definitions
var customPrereqs = map.Rules.Actors.SelectMany(a => a.Value.Traits
.WithInterface<ProvidesCustomPrerequisiteInfo>())
.Select(p => p.Prerequisite);
// ProvidesTechPrerequisite allows arbitrary prereq definitions
// (but only one group at a time during gameplay)
var techPrereqs = map.Rules.Actors.SelectMany(a => a.Value.Traits
.WithInterface<ProvidesTechPrerequisiteInfo>())
.SelectMany(p => p.Prerequisites);
var providedPrereqs = buildingPrereqs.Concat(customPrereqs).Concat(techPrereqs);
// TODO: this check is case insensitive while the real check in-game is not
foreach (var i in map.Rules.Actors)
{
var bi = i.Value.Traits.GetOrDefault<BuildableInfo>();
if (bi != null)
foreach (var prereq in bi.Prerequisites)
if (!prereq.StartsWith("~disabled"))
if (!providedPrereqs.Contains(prereq.Replace("!", "").Replace("~", "")))
emitError("Buildable actor {0} has prereq {1} not provided by anything.".F(i.Key, prereq));
}
}
}
}

View File

@@ -119,10 +119,6 @@
<Compile Include="Traits\DemoTruck.cs" />
<Compile Include="Effects\GpsDot.cs" />
<Compile Include="Effects\Parachute.cs" />
<Compile Include="Lint\CheckActorReferences.cs" />
<Compile Include="Lint\CheckSyncAnnotations.cs" />
<Compile Include="Lint\CheckTraitPrerequisites.cs" />
<Compile Include="Lint\LintBuildablePrerequisites.cs" />
<Compile Include="Traits\MadTank.cs" />
<Compile Include="Traits\Mine.cs" />
<Compile Include="Traits\Minelayer.cs" />
@@ -181,7 +177,6 @@
<Compile Include="Traits\Infiltration\InfiltrateForSupportPower.cs" />
<Compile Include="Traits\Infiltration\Infiltrates.cs" />
<Compile Include="Widgets\Logic\ObserverShroudSelectorLogic.cs" />
<Compile Include="Lint\CheckSequences.cs" />
<Compile Include="Widgets\Logic\SpawnSelectorTooltipLogic.cs" />
<Compile Include="Widgets\Logic\ClientTooltipLogic.cs" />
<Compile Include="Widgets\Logic\CreditsLogic.cs" />
@@ -200,9 +195,6 @@
<Compile Include="Widgets\Logic\LobbyMapPreviewLogic.cs" />
<Compile Include="Widgets\Logic\ControlGroupLogic.cs" />
<Compile Include="Scripting\Properties\ChronosphereProperties.cs" />
<Compile Include="Lint\CheckPlayers.cs" />
<Compile Include="Lint\CheckActors.cs" />
<Compile Include="Lint\CheckMapCordon.cs" />
<Compile Include="Traits\Parachutable.cs" />
<Compile Include="Widgets\Logic\InstallFromCDLogic.cs" />
<Compile Include="Widgets\Logic\InstallMusicLogic.cs" />
@@ -219,7 +211,6 @@
<Compile Include="Scripting\Properties\HarvesterProperties.cs" />
<Compile Include="Scripting\Properties\TransportProperties.cs" />
<Compile Include="Traits\InvulnerabilityUpgrade.cs" />
<Compile Include="Lint\CheckMapRules.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj">