package com.onthegomap.planetiler.experimental.lua; import static org.junit.jupiter.api.Assertions.assertEquals; import com.onthegomap.planetiler.config.Arguments; import java.nio.file.Path; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.Semaphore; import java.util.function.Consumer; import org.junit.jupiter.api.Test; import org.luaj.vm2.LuaDouble; import org.luaj.vm2.LuaInteger; import org.luaj.vm2.LuaNumber; import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.lib.jse.LuaBindMethods; import org.luaj.vm2.lib.jse.LuaFunctionType; import org.luaj.vm2.lib.jse.LuaGetter; import org.luaj.vm2.lib.jse.LuaSetter; @SuppressWarnings("unused") class GenerateLuaTypesTest { @Test void testSimpleClass() { interface Test { String string(); int intMethod(Integer n); long longMethod(Long n); double doubleMethod(Double n); float floatMethod(Float n); short shortMethod(Short n); byte byteMethod(Byte n); boolean booleanMethod(Boolean n); } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test = {} ---@param n boolean ---@return boolean function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:boolean_method(n) end ---@param n integer ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:byte_method(n) end ---@param n number ---@return number function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:double_method(n) end ---@param n number ---@return number function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:float_method(n) end ---@param n integer ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:int_method(n) end ---@param n integer ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:long_method(n) end ---@param n integer ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:short_method(n) end ---@return string function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Test:string() end """, Test.class); } @Test void testSimpleClassWithLuaBindMethods() { @LuaBindMethods interface TestBindMethods { String string(); int intMethod(Integer n); void voidMethod(); } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestBindMethods ---@field int_method fun(n: integer): integer ---@field string fun(): string ---@field void_method fun(): nil types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestBindMethods = {} """, TestBindMethods.class); } @Test void testSimpleClassWithField() { class WithField { public Date field; } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithField ---@field field java_util_Date types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithField = {} """, WithField.class); } @Test void testSimpleClassWithGetter() { class WithGetter { @LuaGetter public Date field() { return null; } @LuaGetter public List field2() { return null; } @LuaSetter public void field2(List value) {} } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithGetter ---@field field java_util_Date ---@field field2 string[] types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithGetter = {} """, WithGetter.class); } @Test void testSimpleClassWithSetter() { class WithSetter { @LuaSetter public void field(Date field) {} } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithSetter ---@field field java_util_Date types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithSetter = {} """, WithSetter.class); } @Test void testArrays() { class WithArrays { public int[] intArray; public Integer[] intObjectArray; public Semaphore[] semaphoreArray; } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithArrays ---@field int_array integer[] ---@field int_object_array integer[] ---@field semaphore_array java_util_concurrent_Semaphore[] types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithArrays = {} """, WithArrays.class); } @Test void testKeywordCollision() { class KeywordCollision { public int and; } assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1KeywordCollision ---@field AND integer types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1KeywordCollision = {} """, KeywordCollision.class); } @Test void testLists() { class WithLists { public List ints; public List dates; public List objs; public List wildcards; } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithLists ---@field dates java_util_Date[] ---@field ints integer[] ---@field objs any[] ---@field wildcards any[] types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1WithLists = {} """, WithLists.class); } @Test void testMaps() { class WithLists { public Map stringToInt; public Map dateToDouble; public Map objectToWildcard; public Map>> stringToDoubleStringList; } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2WithLists ---@field date_to_double {[java_util_Date]: number} ---@field object_to_wildcard {[any]: any} ---@field string_to_double_string_list {[string]: string[][]} ---@field string_to_int {[string]: integer} types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2WithLists = {} """, WithLists.class); } @Test void testMethodOnGenericType() { class Generic { public T value() { return null; } } class Concrete extends Generic {} assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Concrete : com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Generic types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Concrete = {} ---@return string function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Concrete:value() end """, Concrete.class); } @Test void testGenericMethod() { class GenericMethod { public T apply(T input) { return null; } public T applyNumber(T input) { return null; } } assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1GenericMethod types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1GenericMethod = {} ---@generic T ---@param input T ---@return T function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1GenericMethod:apply(input) end ---@generic T : number ---@param input T ---@return T function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1GenericMethod:apply_number(input) end """, GenericMethod.class); } @Test void testGenericMethodInterface() { interface Interface { T value(); } interface ConcreteInterface extends Interface {} assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1ConcreteInterface : com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Interface types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1ConcreteInterface = {} ---@return string function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1ConcreteInterface:value() end """, ConcreteInterface.class); } @Test void testRecord() { record Record(int x, int y) {} assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Record : java_lang_Record ---@field x integer ---@field y integer types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1Record = {} """, Record.class); } @Test void testGenericField() { class Generic { public T field; } class ConcreteField extends Generic {} assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1ConcreteField : com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2Generic ---@field field integer types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1ConcreteField = {} """, ConcreteField.class); } @Test void testLuaValueWithAnnotation() { class Target { public int method(int arg) { return 1; } } class LuaValues { public LuaString string; public LuaInteger integer; public LuaDouble number; public LuaNumber number2; public LuaTable table; @LuaFunctionType( target = Target.class, method = "method" ) public LuaValue value; } assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1LuaValues ---@field integer integer ---@field number number ---@field number2 number ---@field string string ---@field table table ---@field value fun(arg: integer): integer types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1LuaValues = {} """, LuaValues.class); } public static class StaticClassSuper { public static final int SUPER_CONSTANT = 1; public final int superInstanceField = 1; public int superInstance(int arg) { return 1; } public static String superStaticMethod(String arg) { return ""; } } public static class StaticClass extends StaticClassSuper { public static final int CONSTANT = 1; public static int staticField; public int instanceField; public StaticClass() {} public StaticClass(int i) {} public int instance(int arg) { return 1; } public static int staticMethod(int arg) { return 1; } } @Test void testStaticLuaInstanceWithConsructors() { assertGeneratedStatic( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass__class ---@field CONSTANT integer ---@field SUPER_CONSTANT integer ---@field static_field integer types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass__class = {} ---@param i integer ---@return com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass__class:new(i) end ---@return com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass__class:new() end ---@param arg integer ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass__class:static_method(arg) end ---@param arg string ---@return string function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_StaticClass__class:super_static_method(arg) end """ .trim(), StaticClass.class); } @Test void testGenericClassMethod() { assertGenerated( """ ---@class (exact) java_util_function_Consumer types.java_util_function_Consumer = {} ---@param arg0 any ---@return nil function types.java_util_function_Consumer:accept(arg0) end ---@param arg0 java_util_function_Consumer ---@return java_util_function_Consumer function types.java_util_function_Consumer:and_then(arg0) end """, Consumer.class); } @Test void testEnum() { enum TestEnum { A, B, C } assertGenerated( """ ---@alias com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum ---|com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum ---|integer ---|"A" ---|"B" ---|"C" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum : java_lang_Enum types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum = {} ---@param arg0 any ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum:compare_to(arg0) end ---@param arg0 com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum:compare_to(arg0) end ---@return java_util_Optional function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum:describe_constable() end ---@return userdata function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum:get_declaring_class() end ---@return string function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum:name() end ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum__enum:ordinal() end """, TestEnum.class); class UsesEnum { public TestEnum field; public TestEnum method(TestEnum arg) { return null; } } assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1UsesEnum ---@field field com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1UsesEnum = {} ---@param arg com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum ---@return com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1TestEnum function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1UsesEnum:method(arg) end """, UsesEnum.class); } @Test void testPath() { class UsesPath { public Path field; public Path method(Path arg) { return null; } } assertGenerated( """ ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1UsesPath ---@field field java_nio_file_Path types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1UsesPath = {} ---@param arg java_nio_file_Path|string|string[] ---@return java_nio_file_Path function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_1UsesPath:method(arg) end """, UsesPath.class); } @Test void testAbbreviationInName() { interface Test { int setSRID(Integer n); } assertGenerated(""" ---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2Test types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2Test = {} ---@param n integer ---@return integer function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2Test:set_srid(n) end """, Test.class); } @Test void testGeneratedMetaFileCompiles() { String types = new GenerateLuaTypes().generatePlanetiler().toString(); LuaEnvironment.loadScript(Arguments.of("luajc", "false"), types, "types.lua"); } private static void assertGenerated(String expected, Class clazz) { assertGenerated(expected, clazz, false); } private static void assertGeneratedStatic(String expected, Class clazz) { assertGenerated(expected, clazz, true); } private static void assertGenerated(String expected, Class clazz, boolean staticType) { var g = new GenerateLuaTypes(); var actual = (staticType ? g.getStaticTypeDefinition(clazz) : g.getTypeDefinition(clazz)).trim(); assertEquals(fixNewlines(expected.trim()), fixNewlines(actual), "got:%n%n%s%n%n".formatted(actual)); } private static String fixNewlines(String input) { return input.replaceAll("[\n\r]+", System.lineSeparator()); } }