Improve Lua type documentation and bindings.
The ExtractEmmyLuaAPI utility command, invoked with `--emmy-lua-api`, produces a documentation file that is used by the [OpenRA Lua Language Extension](https://marketplace.visualstudio.com/items?itemName=openra.vscode-openra-lua) to provide documentation and type information is VSCode and VSCode compatible editors when editing the Lua scripts. We improve the documentation and types produced by this utility in a few ways: - Require descriptions to be provided for all items. - Fix the type definitions of the base engine types (cpos, wpos, wangle, wdist, wvec, cvec) to match with the actual bindings on the C# side. Add some extra bindings for these types to increase their utility. - Introduce ScriptEmmyTypeOverrideAttribute to allow the C# side of the bindings to provide a more specific type. The utility command now requires this to be used to avoid accidentally exporting poor type information. - Fix a handful of scripts where the new type information revealed warnings. The ability to ScriptEmmyTypeOverrideAttribute allows parameters and return types to provide a more specific type compared to the previous, weak, type definition. For example LuaValue mapped to `any`, LuaTable mapped to `table`, and LuaFunction mapped to `function`. These types are all non-specific. `any` can be anything, `table` is a table without known types for its keys or values, `function` is a function with an unknown signature. Now, we can provide specific types. , e.g. instead of `table`, ReinforcementsGlobal.ReinforceWithTransport is able to specify `{ [1]: actor, [2]: actor[] }` - a table with keys 1 and 2, whose values are an actor, and a table of actors respectively. The callback functions in MapGlobal now have signatures, e.g. instead of `function` we have `fun(a: actor):boolean`. In UtilsGlobal, we also make use of generic types. These work in a similar fashion to generics in C#. These methods operate on collections, we can introduce a generic parameter named `T` for the type of the items in those collections. Now the return type and callback parameters can also use that generic type. This means the return type or callback functions operate on the same type as whatever type is in the collection you pass in. e.g. Utils.Do accepts a collection typed as `T[]` with a callback function invoked on each item typed as `fun(item: T)`. If you pass in actors, the callback operates on an actor. If you pass in strings, the callback operates on a string, etc. Overall, these changes should result in an improved user experience for those editing OpenRA Lua scripts in a compatible IDE.
This commit is contained in:
@@ -16,7 +16,8 @@ using OpenRA.Scripting;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public readonly struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CPos>
|
||||
public readonly struct CPos : IEquatable<CPos>, IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, ILuaToStringBinding
|
||||
{
|
||||
// Coordinates are packed in a 32 bit signed int
|
||||
// X and Y are 12 bits (signed): -2048...2047
|
||||
@@ -96,7 +97,8 @@ namespace OpenRA
|
||||
public LuaValue Add(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out CPos a) || !right.TryGetClrValue(out CVec b))
|
||||
throw new LuaException($"Attempted to call CPos.Add(CPos, CVec) with invalid arguments ({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
throw new LuaException("Attempted to call CPos.Add(CPos, CVec) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a + b);
|
||||
}
|
||||
@@ -105,7 +107,8 @@ namespace OpenRA
|
||||
{
|
||||
var rightType = right.WrappedClrType();
|
||||
if (!left.TryGetClrValue(out CPos a))
|
||||
throw new LuaException($"Attempted to call CPos.Subtract(CPos, (CPos|CVec)) with invalid arguments ({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
throw new LuaException("Attempted to call CPos.Subtract(CPos, (CPos|CVec)) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
|
||||
if (rightType == typeof(CPos))
|
||||
{
|
||||
@@ -118,7 +121,8 @@ namespace OpenRA
|
||||
return new LuaCustomClrObject(a - b);
|
||||
}
|
||||
|
||||
throw new LuaException($"Attempted to call CPos.Subtract(CPos, (CPos|CVec)) with invalid arguments ({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
throw new LuaException("Attempted to call CPos.Subtract(CPos, (CPos|CVec)) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
}
|
||||
|
||||
public LuaValue Equals(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
@@ -145,6 +149,8 @@ namespace OpenRA
|
||||
set => throw new LuaException("CPos is read-only. Use CPos.New to create a new value");
|
||||
}
|
||||
|
||||
public LuaValue ToString(LuaRuntime runtime) => ToString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@ using OpenRA.Scripting;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public readonly struct CVec : IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaUnaryMinusBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CVec>
|
||||
public readonly struct CVec : IEquatable<CVec>, IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaUnaryMinusBinding,
|
||||
ILuaMultiplicationBinding, ILuaDivisionBinding, ILuaTableBinding, ILuaToStringBinding
|
||||
{
|
||||
public readonly int X, Y;
|
||||
|
||||
@@ -77,7 +78,8 @@ namespace OpenRA
|
||||
public LuaValue Add(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out CVec a) || !right.TryGetClrValue(out CVec b))
|
||||
throw new LuaException($"Attempted to call CVec.Add(CVec, CVec) with invalid arguments ({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
throw new LuaException("Attempted to call CVec.Add(CVec, CVec) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a + b);
|
||||
}
|
||||
@@ -85,16 +87,12 @@ namespace OpenRA
|
||||
public LuaValue Subtract(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out CVec a) || !right.TryGetClrValue(out CVec b))
|
||||
throw new LuaException($"Attempted to call CVec.Subtract(CVec, CVec) with invalid arguments ({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
throw new LuaException("Attempted to call CVec.Subtract(CVec, CVec) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a - b);
|
||||
}
|
||||
|
||||
public LuaValue Minus(LuaRuntime runtime)
|
||||
{
|
||||
return new LuaCustomClrObject(-this);
|
||||
}
|
||||
|
||||
public LuaValue Equals(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out CVec a) || !right.TryGetClrValue(out CVec b))
|
||||
@@ -103,6 +101,29 @@ namespace OpenRA
|
||||
return a == b;
|
||||
}
|
||||
|
||||
public LuaValue Minus(LuaRuntime runtime)
|
||||
{
|
||||
return new LuaCustomClrObject(-this);
|
||||
}
|
||||
|
||||
public LuaValue Multiply(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out CVec a) || !right.TryGetClrValue(out int b))
|
||||
throw new LuaException("Attempted to call CVec.Multiply(CVec, integer) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a * b);
|
||||
}
|
||||
|
||||
public LuaValue Divide(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out CVec a) || !right.TryGetClrValue(out int b))
|
||||
throw new LuaException("Attempted to call CVec.Multiply(CVec, integer) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a / b);
|
||||
}
|
||||
|
||||
public LuaValue this[LuaRuntime runtime, LuaValue key]
|
||||
{
|
||||
get
|
||||
@@ -111,6 +132,7 @@ namespace OpenRA
|
||||
{
|
||||
case "X": return X;
|
||||
case "Y": return Y;
|
||||
case "Length": return Length;
|
||||
default: throw new LuaException($"CVec does not define a member '{key}'");
|
||||
}
|
||||
}
|
||||
@@ -118,6 +140,8 @@ namespace OpenRA
|
||||
set => throw new LuaException("CVec is read-only. Use CVec.New to create a new value");
|
||||
}
|
||||
|
||||
public LuaValue ToString(LuaRuntime runtime) => ToString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace OpenRA
|
||||
/// <summary>
|
||||
/// 1D angle - 1024 units = 360 degrees.
|
||||
/// </summary>
|
||||
public readonly struct WAngle : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, IEquatable<WAngle>
|
||||
public readonly struct WAngle : IEquatable<WAngle>, IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, ILuaToStringBinding
|
||||
{
|
||||
public readonly int Angle;
|
||||
public int AngleSquared => Angle * Angle;
|
||||
@@ -257,6 +258,22 @@ namespace OpenRA
|
||||
return a == b;
|
||||
}
|
||||
|
||||
public LuaValue this[LuaRuntime runtime, LuaValue key]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (key.ToString())
|
||||
{
|
||||
case "Angle": return Angle;
|
||||
default: throw new LuaException($"WAngle does not define a member '{key}'");
|
||||
}
|
||||
}
|
||||
|
||||
set => throw new LuaException("WAngle is read-only. Use Angle.New to create a new value");
|
||||
}
|
||||
|
||||
public LuaValue ToString(LuaRuntime runtime) => ToString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,10 @@ namespace OpenRA
|
||||
/// <summary>
|
||||
/// 1d world distance - 1024 units = 1 cell.
|
||||
/// </summary>
|
||||
public readonly struct WDist : IComparable, IComparable<WDist>, IEquatable<WDist>,
|
||||
IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding
|
||||
public readonly struct WDist : IComparable, IComparable<WDist>, IEquatable<WDist>, IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaUnaryMinusBinding,
|
||||
ILuaMultiplicationBinding, ILuaDivisionBinding, ILuaLessThanBinding, ILuaLessThanOrEqualToBinding,
|
||||
ILuaTableBinding, ILuaToStringBinding
|
||||
{
|
||||
public readonly int Length;
|
||||
public long LengthSquared => (long)Length * Length;
|
||||
@@ -137,6 +139,40 @@ namespace OpenRA
|
||||
return a == b;
|
||||
}
|
||||
|
||||
public LuaValue Minus(LuaRuntime runtime) => new LuaCustomClrObject(-this);
|
||||
|
||||
public LuaValue Multiply(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WDist a) || !right.TryGetClrValue(out int b))
|
||||
throw new LuaException("Attempted to call WDist.Multiply(WDist, integer) with invalid arguments.");
|
||||
|
||||
return new LuaCustomClrObject(a * b);
|
||||
}
|
||||
|
||||
public LuaValue Divide(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WDist a) || !right.TryGetClrValue(out int b))
|
||||
throw new LuaException("Attempted to call WDist.Divide(WDist, integer) with invalid arguments.");
|
||||
|
||||
return new LuaCustomClrObject(a / b);
|
||||
}
|
||||
|
||||
public LuaValue LessThan(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WDist a) || !right.TryGetClrValue(out WDist b))
|
||||
throw new LuaException("Attempted to call WDist.LessThan(WDist, WDist) with invalid arguments.");
|
||||
|
||||
return a < b;
|
||||
}
|
||||
|
||||
public LuaValue LessThanOrEqualTo(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WDist a) || !right.TryGetClrValue(out WDist b))
|
||||
throw new LuaException("Attempted to call WDist.LessThanOrEqualTo(WDist, WDist) with invalid arguments.");
|
||||
|
||||
return a <= b;
|
||||
}
|
||||
|
||||
public LuaValue this[LuaRuntime runtime, LuaValue key]
|
||||
{
|
||||
get
|
||||
@@ -150,6 +186,9 @@ namespace OpenRA
|
||||
|
||||
set => throw new LuaException("WDist is read-only. Use WDist.New to create a new value");
|
||||
}
|
||||
|
||||
public LuaValue ToString(LuaRuntime runtime) => ToString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ using OpenRA.Scripting;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public readonly struct WPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<WPos>
|
||||
public readonly struct WPos : IEquatable<WPos>, IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, ILuaToStringBinding
|
||||
{
|
||||
public readonly int X, Y, Z;
|
||||
|
||||
@@ -82,7 +83,8 @@ namespace OpenRA
|
||||
public LuaValue Add(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WPos a) || !right.TryGetClrValue(out WVec b))
|
||||
throw new LuaException($"Attempted to call WPos.Add(WPos, WVec) with invalid arguments ({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
throw new LuaException("Attempted to call WPos.Add(WPos, WVec) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a + b);
|
||||
}
|
||||
@@ -91,7 +93,8 @@ namespace OpenRA
|
||||
{
|
||||
var rightType = right.WrappedClrType();
|
||||
if (!left.TryGetClrValue(out WPos a))
|
||||
throw new LuaException($"Attempted to call WPos.Subtract(WPos, (WPos|WVec)) with invalid arguments ({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
throw new LuaException("Attempted to call WPos.Subtract(WPos, (WPos|WVec)) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
|
||||
if (rightType == typeof(WPos))
|
||||
{
|
||||
@@ -104,7 +107,8 @@ namespace OpenRA
|
||||
return new LuaCustomClrObject(a - b);
|
||||
}
|
||||
|
||||
throw new LuaException($"Attempted to call WPos.Subtract(WPos, (WPos|WVec)) with invalid arguments ({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
throw new LuaException("Attempted to call WPos.Subtract(WPos, (WPos|WVec)) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {rightType.Name})");
|
||||
}
|
||||
|
||||
public LuaValue Equals(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
@@ -131,6 +135,8 @@ namespace OpenRA
|
||||
set => throw new LuaException("WPos is read-only. Use WPos.New to create a new value");
|
||||
}
|
||||
|
||||
public LuaValue ToString(LuaRuntime runtime) => ToString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@ using OpenRA.Support;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public readonly struct WVec : IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaUnaryMinusBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<WVec>
|
||||
public readonly struct WVec : IEquatable<WVec>, IScriptBindable,
|
||||
ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaUnaryMinusBinding,
|
||||
ILuaMultiplicationBinding, ILuaDivisionBinding, ILuaTableBinding, ILuaToStringBinding
|
||||
{
|
||||
public readonly int X, Y, Z;
|
||||
|
||||
@@ -112,7 +113,8 @@ namespace OpenRA
|
||||
public LuaValue Add(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WVec a) || !right.TryGetClrValue(out WVec b))
|
||||
throw new LuaException($"Attempted to call WVec.Add(WVec, WVec) with invalid arguments ({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
throw new LuaException("Attempted to call WVec.Add(WVec, WVec) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a + b);
|
||||
}
|
||||
@@ -120,16 +122,12 @@ namespace OpenRA
|
||||
public LuaValue Subtract(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WVec a) || !right.TryGetClrValue(out WVec b))
|
||||
throw new LuaException($"Attempted to call WVec.Subtract(WVec, WVec) with invalid arguments ({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
throw new LuaException("Attempted to call WVec.Subtract(WVec, WVec) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a - b);
|
||||
}
|
||||
|
||||
public LuaValue Minus(LuaRuntime runtime)
|
||||
{
|
||||
return new LuaCustomClrObject(-this);
|
||||
}
|
||||
|
||||
public LuaValue Equals(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WVec a) || !right.TryGetClrValue(out WVec b))
|
||||
@@ -138,6 +136,29 @@ namespace OpenRA
|
||||
return a == b;
|
||||
}
|
||||
|
||||
public LuaValue Minus(LuaRuntime runtime)
|
||||
{
|
||||
return new LuaCustomClrObject(-this);
|
||||
}
|
||||
|
||||
public LuaValue Multiply(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WVec a) || !right.TryGetClrValue(out int b))
|
||||
throw new LuaException("Attempted to call WVec.Multiply(WVec, integer) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a * b);
|
||||
}
|
||||
|
||||
public LuaValue Divide(LuaRuntime runtime, LuaValue left, LuaValue right)
|
||||
{
|
||||
if (!left.TryGetClrValue(out WVec a) || !right.TryGetClrValue(out int b))
|
||||
throw new LuaException("Attempted to call WVec.Divide(WVec, integer) with invalid arguments " +
|
||||
$"({left.WrappedClrType().Name}, {right.WrappedClrType().Name})");
|
||||
|
||||
return new LuaCustomClrObject(a / b);
|
||||
}
|
||||
|
||||
public LuaValue this[LuaRuntime runtime, LuaValue key]
|
||||
{
|
||||
get
|
||||
@@ -155,6 +176,8 @@ namespace OpenRA
|
||||
set => throw new LuaException("WVec is read-only. Use WVec.New to create a new value");
|
||||
}
|
||||
|
||||
public LuaValue ToString(LuaRuntime runtime) => ToString();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user