Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 79 additions & 31 deletions LuaDefinitionMaker/BasicType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,38 @@ public BasicType(Type baseType, string name, LuaDefinitionAttribute attribute, T
this.fallbackType = fallbackType;
}

private static void writeDeprecated(StringBuilder sb, MemberInfo member, bool withMessage = true)
{
var obs = member.GetCustomAttribute<ObsoleteAttribute>(false);
if (obs is null) return;

if (withMessage && !string.IsNullOrWhiteSpace(obs.Message))
sb.AppendLine($"---{obs.Message.ReplaceLineEndings(" ")}");

sb.AppendLine("---@deprecated");
}

private static string? getObsoleteMessage(MemberInfo member)
{
var obs = member.GetCustomAttribute<ObsoleteAttribute>(false);
return string.IsNullOrWhiteSpace(obs?.Message) ? null : obs.Message.ReplaceLineEndings(" ");
}

private static IEnumerable<(T Member, string Name)> getNewestMember<T>(IEnumerable<(T Member, string Name)> items)
where T : MemberInfo
=> items.GroupBy(x => x.Name)
.Select(g =>
g.OrderByDescending(x => x.Member.GetCustomAttribute<LuaVersionAttribute>()?.Since ?? 0)
.First()
);

public override void Write(StringBuilder sb)
{
Program.Write($"{Attribute.FileName}: {BaseType.FullName}");

if (!Attribute.Hide)
{
writeDeprecated(sb, BaseType);
sb.Append($"---@class {Name}");

if (BaseType.BaseType != null)
Expand All @@ -38,6 +64,8 @@ public override void Write(StringBuilder sb)

sb.AppendLine();

var propFields = new List<(PropertyInfo Member, string Name)>();

foreach (var prop in BaseType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
var memberAttr = prop.GetCustomAttribute<LuaMemberAttribute>();
Expand All @@ -53,20 +81,33 @@ public override void Write(StringBuilder sb)
if (fieldName is null)
continue;

sb.Append($"---@field {StringUtils.ToCamelCase(fieldName)} {Program.GetLuaType(prop.PropertyType, fallback: fallbackType)}");
propFields.Add((prop, StringUtils.ToCamelCase(fieldName)));
}

foreach (var (prop, fieldName) in getNewestMember(propFields))
{
writeDeprecated(sb, prop, withMessage: false);
sb.Append($"---@field {fieldName} {Program.GetLuaType(prop.PropertyType, fallback: fallbackType)}");

var sum = Documentation.GetPropertySummary(prop);
if (sum is not null) sb.Append($" {sum.ReplaceLineEndings(" ")}");

var obsMsg = getObsoleteMessage(prop);
if (obsMsg is not null) sb.Append($" (deprecated: {obsMsg})");

sb.AppendLine();
}

foreach (var field in BaseType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
var memberAttr = field.GetCustomAttribute<LuaMemberAttribute>();
if (memberAttr is null) continue;
var fieldMembers = BaseType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Select(f => (Member: f, Attr: f.GetCustomAttribute<LuaMemberAttribute>()))
.Where(x => x.Attr is not null)
.Select(x => (x.Member, x.Attr!.Name))
.ToList();

sb.Append($"---@field {memberAttr.Name} {Program.GetLuaType(field.FieldType, fallback: fallbackType)}");
foreach (var (field, name) in getNewestMember(fieldMembers))
{
writeDeprecated(sb, field, withMessage: false);
sb.Append($"---@field {name} {Program.GetLuaType(field.FieldType, fallback: fallbackType)}");
sb.AppendLine();
}

Expand All @@ -78,28 +119,34 @@ public override void Write(StringBuilder sb)
sb.AppendLine();
}

foreach (var property in BaseType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
var globalAttr = property.GetCustomAttribute<LuaGlobalAttribute>();
if (globalAttr is null) continue;
var instanceGlobals = BaseType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Select(p => (Member: p, Attr: p.GetCustomAttribute<LuaGlobalAttribute>()))
.Where(x => x.Attr is not null)
.Select(x => (x.Member, Name: x.Attr!.Name ?? x.Member.Name))
.ToList();

foreach (var (property, globalName) in getNewestMember(instanceGlobals))
{
writeDeprecated(sb, property);
sb.AppendLine($"---@type {Program.GetLuaType(property.PropertyType, fallback: fallbackType)}");
sb.AppendLine($"---@diagnostic disable-next-line: missing-fields");
sb.AppendLine($"{globalAttr.Name ?? property.Name} = {{}}");
sb.AppendLine($"{globalName} = {{}}");
sb.AppendLine();
}

// handle static (global) properties separately
foreach (var prop in BaseType.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
var globalAttr = prop.GetCustomAttribute<LuaGlobalAttribute>();
if (globalAttr is null) continue;

var fieldName = globalAttr.Name ?? prop.Name;
var staticGlobals = BaseType.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly)
.Select(p => (Member: p, Attr: p.GetCustomAttribute<LuaGlobalAttribute>()))
.Where(x => x.Attr is not null)
.Select(x => (x.Member, Name: x.Attr!.Name ?? x.Member.Name))
.ToList();

foreach (var (prop, fieldName) in getNewestMember(staticGlobals))
{
var sum = Documentation.GetPropertySummary(prop);
if (sum is not null) sb.AppendLine($"---{sum.ReplaceLineEndings(" ")}");

writeDeprecated(sb, prop);
sb.AppendLine($"---@type {Program.GetLuaType(prop.PropertyType, fallback: fallbackType)}");
sb.AppendLine($"---@diagnostic disable-next-line: missing-fields");
sb.AppendLine($"{Name}.{fieldName} = {{}}");
Expand All @@ -111,6 +158,8 @@ public override void Write(StringBuilder sb)
var ctorAttr = ctor.GetCustomAttribute<LuaConstructorAttribute>();
if (ctorAttr is null) continue;

writeDeprecated(sb, ctor);

foreach (var parameter in ctor.GetParameters())
{
var pType = parameter.GetCustomAttribute<LuaCustomType>()?.Target ?? parameter.ParameterType;
Expand All @@ -122,12 +171,16 @@ public override void Write(StringBuilder sb)
sb.AppendLine();
}

foreach (var method in BaseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
var memberAttr = method.GetCustomAttribute<LuaMemberAttribute>();
var globalAttr = method.GetCustomAttribute<LuaGlobalAttribute>();
if (memberAttr is null && globalAttr is null) continue;
var methods = BaseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Select(m => (Method: m, Member: m.GetCustomAttribute<LuaMemberAttribute>(), Global: m.GetCustomAttribute<LuaGlobalAttribute>()))
.Where(x => x.Member is not null || x.Global is not null)
.Select(x => (x.Method, Name: x.Global is not null
? x.Global.Name ?? x.Method.Name
: $"{(Attribute.Public ? "" : "__")}{Name}:{x.Member!.Name}"))
.ToList();

foreach (var (method, funcName) in getNewestMember(methods))
{
var doc = Documentation.GetMethod(method);

if (doc.Summary is not null)
Expand All @@ -137,11 +190,13 @@ public override void Write(StringBuilder sb)
foreach (var line in lines) sb.AppendLine($"---{line}");
}

writeDeprecated(sb, method);

foreach (var parameter in method.GetParameters())
{
var pType = parameter.GetCustomAttribute<LuaCustomType>()?.Target ?? parameter.ParameterType;
bool isNullable = parameter.HasDefaultValue && parameter.DefaultValue == null ||
Nullable.GetUnderlyingType(pType) != null;
Nullable.GetUnderlyingType(pType) != null;

var luaType = Program.GetLuaType(pType, false, typeof(string), isNullable);

Expand All @@ -166,14 +221,7 @@ public override void Write(StringBuilder sb)
sb.AppendLine($"---@nodiscard");
}

sb.Append("function ");

if (globalAttr is not null)
sb.Append(globalAttr.Name ?? method.Name);
else if (memberAttr is not null)
sb.Append($"{(Attribute.Public ? "" : "__")}{Name}:{memberAttr.Name}");

sb.AppendLine($"({string.Join(", ", method.GetParameters().Select(x => x.Name))}) end");
sb.AppendLine($"function {funcName}({string.Join(", ", method.GetParameters().Select(x => x.Name))}) end");
sb.AppendLine();
}
}
Expand Down
4 changes: 4 additions & 0 deletions LuaDefinitionMaker/NamespaceTypes.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using fluXis.Scripting.Attributes;
using NLua;
Expand All @@ -19,6 +20,9 @@ public NamespaceTypes(Type[] types, string[] namespaces, string fileName)
// will define types for all classes and structs
this.types = types.Where(t =>
!t.IsAbstract &&
!t.IsNested &&
t.GetCustomAttribute<CompilerGeneratedAttribute>() == null &&
!t.Name.Contains('<') &&
namespaces.Contains(t.Namespace) &&
(t.IsClass || t is { IsValueType: true, IsPrimitive: false, IsEnum: false })
);
Expand Down
10 changes: 0 additions & 10 deletions LuaDefinitionMaker/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
using System.Xml;
using fluXis;
using fluXis.Audio.FFT.Structures.Data;
using fluXis.Map.Structures.Events;
using fluXis.Scripting.Attributes;
using fluXis.Scripting.Models.Storyboarding;
using fluXis.Storyboards;
using osu.Framework.Graphics;

Expand Down Expand Up @@ -61,14 +59,6 @@ private static void Main()
typeList.Add(new EnumType<DefaultBlendingParameters>(true, ctorName: "BlendMode", enumName: "BlendMode"));
typeList.Add(new EnumType<FFTBandType>(false));

var eventTypes = LuaMap.GetMapEventTypes();
eventTypes.Remove(typeof(NoteEvent));

var eventSb = new StringBuilder();
eventSb.AppendLine("---@alias EventType string");
eventTypes.ForEach(x => eventSb.AppendLine($"---| \"{x.Name.Replace("Event", "")}\""));
typeList.Add(new CustomTextType("enums", eventSb.ToString()));

// yes this is stupid but i don't want to figure out how to make it right
typeList.Add(new CustomTextType("enums", "---@alias ParameterDefinitionType string\n---| \"string\"\n---| \"int\"\n---| \"float\"\n---| \"boolean\""));
typeList.Add(new EnumType<StoryboardAnimationType>(false, "AnimationType", "storyboard"));
Expand Down
2 changes: 2 additions & 0 deletions fluXis.Mode.Keys/Objects/Landmine.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using fluXis.Map.Structures;
using rhym;
using fluXis.Scoring.Enums;

namespace fluXis.Mode.Keys.Objects;

[ResourceLocation("flux:keys/mine")]
public class Landmine : HitObject
{
public override float DensityContribution => 0;
Expand Down
2 changes: 2 additions & 0 deletions fluXis.Mode.Keys/Objects/LongNote.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using fluXis.Map.Structures;
using fluXis.Map.Structures.Bases;
using rhym;

namespace fluXis.Mode.Keys.Objects;

[ResourceLocation("flux:keys/long")]
public class LongNote : HitObject, IHasDuration
{
public override int ComboContribution => 2;
Expand Down
2 changes: 2 additions & 0 deletions fluXis.Mode.Keys/Objects/LongNoteTail.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using fluXis.Map.Structures;
using rhym;
using fluXis.Scoring.Enums;

namespace fluXis.Mode.Keys.Objects;

[ResourceLocation("flux:keys/tail")]
public class LongNoteTail : HitObject
{
public override bool ShouldShowJudgement(Judgement judgement) => false;
Expand Down
2 changes: 2 additions & 0 deletions fluXis.Mode.Keys/Objects/Note.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using fluXis.Map.Structures;
using rhym;

namespace fluXis.Mode.Keys.Objects;

[ResourceLocation("flux:keys/note")]
public class Note : HitObject;
2 changes: 2 additions & 0 deletions fluXis.Mode.Keys/Objects/Tick.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using fluXis.Map.Structures;
using rhym;

namespace fluXis.Mode.Keys.Objects;

[ResourceLocation("flux:keys/tick")]
public class Tick : HitObject
{
public override float DensityContribution => 0.1f;
Expand Down
2 changes: 2 additions & 0 deletions fluXis/Map/Structures/Events/ScrollVelocity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
using Newtonsoft.Json;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using rhym;
using YamlDotNet.Serialization;

namespace fluXis.Map.Structures.Events;

[DoNotShowInEditorPlayfield]
[Description("Changes note and scroll velocity.")]
[ResourceLocation("flux:events/scroll/velocity")]
public class ScrollVelocity : ITimedObject, IHasGroups, IScrollEvent
{
[JsonProperty("time")]
Expand Down
2 changes: 2 additions & 0 deletions fluXis/Map/Structures/TimingPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
using Newtonsoft.Json;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using rhym;
using YamlDotNet.Serialization;

namespace fluXis.Map.Structures;

[Description("Changes the BPM and time signature.")]
[ResourceLocation("flux:timing")]
public class TimingPoint : ITimedObject
{
[JsonProperty("time")]
Expand Down
3 changes: 2 additions & 1 deletion fluXis/Screens/Edit/Editor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ private void load(AudioManager audioManager, GameHost host, FluXisConfig config,
new ResourceLocation("flux", "keys/4")
) { Creator = EditorMap.RealmMap.Metadata.Mapper };

EditorMap.Playable.Storyboard ??= new Storyboard { Version = Storyboard.LATEST_VERSION };
// Set to latest api version to avoid starting at V1
EditorMap.Playable.Storyboard ??= new Storyboard { Version = StoryboardApiVersion.LATEST };

GameMode = modes.Find(EditorMap.Playable.Mode) ?? throw GameModeManager.FailedToLoadException();
Format = modes.GetFormat(EditorMap.Playable.Storage, Path.GetExtension(EditorMap.Playable.FileName));
Expand Down
3 changes: 3 additions & 0 deletions fluXis/Scripting/LuaNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ public class LuaNative

[DllImport(dll_name, CallingConvention = CallingConvention.Cdecl)]
internal static extern int luaopen_math(IntPtr state);

[DllImport(dll_name, CallingConvention = CallingConvention.Cdecl)]
internal static extern int luaopen_utf8(IntPtr state);
}
12 changes: 12 additions & 0 deletions fluXis/Scripting/LuaVersionAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace fluXis.Scripting;

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class LuaVersionAttribute : Attribute
{
public int Since { get; init; } = 1;
public int Until { get; init; } = int.MaxValue;

public bool Supports(int v) => v >= Since && v <= Until;
}
30 changes: 30 additions & 0 deletions fluXis/Scripting/LuaVersionResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;

namespace fluXis.Scripting;

public interface IVersionedCandidate
{
[CanBeNull]
LuaVersionAttribute Version { get; }
}

public static class LuaVersionResolver
{
[CanBeNull]
public static T SelectBestMatch<T>(IEnumerable<T> candidates, int version, string label = "Member")
where T : class, IVersionedCandidate
{
var matches = candidates
.Where(c => c.Version?.Supports(version) ?? true)
.OrderByDescending(c => c.Version?.Since ?? 0)
.ToList();

if (matches.Count > 1 && (matches[0].Version?.Since ?? 0) == (matches[1].Version?.Since ?? 0))
throw new InvalidOperationException($"'{label}': Ambiguous candidate for version {version}");

return matches.FirstOrDefault();
}
}
Loading
Loading